__getitem__   在对实例或对象使用索引访问时调用,self[key]
__dir__     收集当前模块的信息,包括继承自其它基类(包括object类)的属性和方法
__new      定义如何创建实例
__init__      构造方法,实例创建时如何初始化
__del__      析构方法,对象在内存中被释放时,自动触发执行
__file__        当前文件在系统中的绝对路径
__hash__     hash值相同表示hash冲突,但并不代表对象值相同。列表不可hash,元组可hash。
          内建类型集合(set)的源码中就用到了"__hash__ = None",来表示set是不可hash类型。
          hash()等同于调用__hash__()方法
        isinstance(1,hashable) 是否可hash
__equal__    == 判断是否相等
      a == b 等价于
      a.__equal__(b)
__bool__      返回bool()布尔值,__bool__() --> __len__() 搜索顺序。
      如果没有__bool__(),则调用__len__()返回长度,非0就为真。
       如果__len__也没有定义,则所有实例都为真

可视化相关的魔术方法:
__repr__    重写表现形式,__str__ --> __repr__ --> object 查找顺序。至少有个__repr__
__str__      format(),print(),str()函数调用时使用的方法,如果没有__str__,则调用__repr__方法,所以这两个方法尽量写一样。
__bytes__      在对象使用bytes()函数时调用此方法
__ascii__

——————————————————————————————————————

运算符重载

容器
__len__     元素个数,必须大于等于0
        size有可能是容器的大小
__iter__     迭代容器时调用,返回一个新的迭代器对象
__contains__   in成员运算符 __contains__ --> __iter__顺序
__getitem__   返回self[key] 的值,不存在返回KeyError异常
__setitem__
__missing__   调用__getitem__时,key不存在时触发,以免抛异常

链式编程

深入学习综合症

__repr__ = __str__

——————————————————————————————————————————————

运算符重载,+= 举例:

class A:
def __init__(self,x):
self.x = x
def __repr__(self):
return str(self.x)
def __iadd__(self, other):
# return A(self.x + other.x) #生成新对象
self.x = self.x + other.x #就地修改
return self a1 = A(4)
a2 = A(10)
a3 = A(5)
print(id(a1),id(a2),id(a3))
a1 += a2
print(id(a1),a1)
~~~~~~
4362338144 4362338200 4362338256
4362338144 14 #对比可以看到前后的id(a1)内存地址一致,为就地修改

  上面例子是就地修改,下面这个例子是生成新对象,对比id(a1)内存地址。

class A:
def __init__(self,x):
self.x = x
def __repr__(self):
return str(self.x)
def __iadd__(self, other):
return A(self.x + other.x) #生成新对象
# self.x = self.x + other.x #就地修改
# return self a1 = A(4)
a2 = A(10)
a3 = A(5)
print(id(a1),id(a2),id(a3))
a1 += a2
print(id(a1),a1)
~~~~~~~~~~~~~~~~~~
4362338088 4362338144 4362338200
4362604616 14 #id(a1)值不等,生成的是新对象

  

练习:
设计二维坐标类Point,使其成为可hash类型,并比较2个坐标的实例是否相等。
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __str__(self):
return '{},{}'.format(self.x,self.y)
def __eq__(self, other):
return (self.x == other.x) and (self.y == other.y)
def __iadd__(self, other):
return Point((self.x + other.x),(self.y + other.y)) p1 = Point(4,5)
p2 = Point(6,5) print(p1 == p2)
p1 += p2
print(p1)

  

练习:
购物车支持索引的方式检索商品:
class Color:
RED = 0
BLACK = 1
WHITE = 2
BLUE = 3 class Item:
def __init__(self,**kwargs):
self.spec = kwargs
def __repr__(self):
return str(sorted(self.spec.items()))
def __str__(self):
return str(sorted(self.spec.items()))
def __getitem__(self, item):
return self.spec.items()[item] class Cart:
def __init__(self):
self.items = []
def addItems(self,item):
self.items.append(item)
def getAllItems(self):
return self.items
def __add__(self, other): # +
pass
def __len__(self):
return len(self.getAllItems())
def __iter__(self):
return iter(self.items)
# for item in self.getAllItems():
# yield item
def __getitem__(self, index): #index
return self.items[index]
def __missing__(self, key): #只支持字典
print(key)
def __setitem__(self, key, value): #索引不可以超界
self.items[key] = value
return self.items mycart = Cart()
mycar = Item(mark='tesla',color=Color.WHITE,price='100w',speed='400km/h',year=2017)
myphone = Item(mark='Nokia',color=Color.BLACK,price=5000,memory='4G')
mymac = Item(mark='MacPro',color=Color.WHITE,price=19999,memory='16G',ssd='512G')
mycart.addItems(mycar)
mycart.addItems(myphone)
mycart.addItems(mymac)
for item in mycart.getAllItems():
# for item in mycart:
print(item.__dict__)
print(mycart.__len__())
print(mycart[2])

  

练习:斐波那契数列支持索引方式查找第n个数字。索引和调用两种方式:
class Fib:
"""0,1,1,2,3,5,8,13,21""" def __init__(self):
self.lst = [] def __call__(self, n, *args, **kwargs):
i = 0
prev, next = 0, 1
while True:
self.lst.append(prev)
if i == n:
return prev
prev, next = next, prev + next
i += 1 def __getitem__(self, item):
return self.__call__(item) f1 = Fib()
# print(f1(7))
# print(f1(8))
print(f1[8])

  

回顾下普通装饰器
import datetime
import time def timer(fn):
def wrapper(x, y):
start = datetime.datetime.now()
print('start:',start)
print(fn(x, y))
time.sleep(1)
stop = datetime.datetime.now()
# print('stop: ',stop)
return 'stop: {}'.format(stop) return wrapper @timer
def add(x, y):
return x + y num1 = add(3, 4)
print(num1)

  

上下文管理
类作为上下文,进入上下文时如果有定义__enter__方法,则做该方法的动作。
__enter__ 进去了帮我做某事,
__exit__ 离开时候帮忙
必须同时存在
import sys
sys.exit() 强制退出脚本
异常退出时处理
exc_type
exc_val
exc_tb traceback 类装饰器
两个装饰器同时装饰
with TimeIt() as f:
pass from functools import wrapås
@wraps(fn)
def self().... == wraps(fn)(self) 复制所有属性
类装饰是调用到__init__ 和__call__
--—————————————————————————————————————————————— ————————————————————————————————————————————————

  

用类做装饰器,调用的是__enter__和__exit__:
import datetime
import time class TimeIt:
def __init__(self, fn):
print('__init__...')
self.fn = fn def __enter__(self):
self.start = datetime.datetime.now()
print('Enter:', self.start)
return self def __call__(self, *args, **kwargs):
print('__call__....')
self.start = datetime.datetime.now()
print('Enter:', self.start)
print(self.fn(*args, **kwargs))
self.stop = datetime.datetime.now()
# print('Exit:', self.stop)
return 'Exit: {}'.format(self.stop) def __exit__(self, exc_type, exc_val, exc_tb):
self.stop = datetime.datetime.now()
print('Exit:', self.stop)
return self @TimeIt
def add(x, y):
time.sleep(1)
return x + y # with TimeIt(add) as foo:
# print(foo(3,4)) print(add(3, 4))

  

使用wraps的方式,拷贝所有属性:
import time
import datetime
from functools import wraps class TimeIt: def __init__(self, fn):
# self.__doc__ = fn.__doc__
print('init')
self._fn = fn
wraps(fn)(self)
#@wraps(fn) 等同于
#def self()...... def __enter__(self):
print('enter')
self.start = datetime.datetime.now()
return self def __call__(self, *args, **kwargs):
print('__call__')
start = datetime.datetime.now()
ret = self._fn(*args, **kwargs)
delta = (datetime.datetime.now() - start).total_seconds()
print("dec {} took {}".format(self._fn.__name__, delta))
return ret def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
delta = (datetime.datetime.now() - self.start).total_seconds()
print("context {} took {}".format(self._fn.__name__, delta))
return # def logger(fn):
# @wraps(fn)
# def wrapper(*args, **kwargs):
# start = datetime.datetime.now()
# ret = fn(*args, **kwargs)
# delta = (datetime.datetime.now() - start).total_seconds()
# print("dec {} took {}".format(fn.__name__, delta))
# return ret
# return wrapper @TimeIt
def add(x,y): # add = TimeIt(add)
"""This is a add function.~~~~~~~~~~~~~~~"""
time.sleep(2)
return x + y print(add(10,11)) print(add.__doc__)
print(add.__name__) print(add.__dict__)
# with TimeIt(add) as foo:
# print(foo(5, 16))

  

Python 面向对象(三) 魔术方法的更多相关文章

  1. Python - 面向对象编程 - 魔术方法(双下划线方法)

    什么是魔术方法 在Python中,所有以 __ 双下划线包起来的方法,都统称为 Magic Method 魔术方法,也叫双下划线方法 有哪些重要的魔术方法? __new__ https://www.c ...

  2. Python面向对象之魔术方法

    __str__ 改变对象的字符串显示.可以理解为使用print函数打印一个对象时,会自动调用对象的__str__方法 class Student: def __init__(self, name, a ...

  3. 十八、Python面向对象之魔术方法

    1.类的比较 class A(object): def __init__(self,value): self.value = value def __eq__(self,other): return ...

  4. Python 类的魔术方法

    Python中类的魔术方法 在Python中以两个下划线开头的方法,__init__.__str__.__doc__.__new__等,被称为"魔术方法"(Magic method ...

  5. Python面向对象三要素-继承(Inheritance)

    Python面向对象三要素-继承(Inheritance) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.继承概述 1>.基本概念 前面我们学习了Python的面向对象三 ...

  6. Python面向对象三要素-封装(Encapsulation)

    Python面向对象三要素-封装(Encapsulation) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.封装概述 将数据和操作组织到类中,即属性和方法 将数据隐藏起来,给 ...

  7. mac学习Python第一天:安装、软件说明、运行python的三种方法

    一.Python安装 从Python官网下载Python 3.x的安装程序,下载后双击运行并安装即可: Python有两个版本,一个是2.x版,一个是3.x版,这两个版本是不兼容的. MAC 系统一般 ...

  8. Python学习笔记之面向对象编程(三)Python类的魔术方法

    python类中有一些方法前后都有两个下划线,这类函数统称为魔术方法.这些方法有特殊的用途,有的不需要我们自己定义,有的则通过一些简单的定义可以实现比较神奇的功能 我主要把它们分为三个部分,下文也是分 ...

  9. Python中的魔术方法详解

    介绍 在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”,中文称『魔术方法』,例如类的初始化方法 __init__ ,Python中所有的魔术方法均在官方文档中 ...

随机推荐

  1. 【学习】js学习笔记:数组(一)

    1.创建数组并赋值 //对象方式 var arr=new Array(1,2,3,4); //隐形声明方式 var arr2=[5,6,7,8]; 2.数组可以存储任何类型的数据 3.访问数组,是用下 ...

  2. 59、jQuery初识

    jQuery是由原生js写的所以说所有jQuery制作出来的效果都可以使用js做出来,jQuery出现的目的是为了优化代码,提高码代码的效率它将很多功能封装. 一.jQuery的认识 1.何为jque ...

  3. WPF checkbox文字下掉

    WPF checkbox文字下掉 可以使用 <Style TargetType="CheckBox"> <Setter Property="Margin ...

  4. 恶意软件Mirai换了个马甲 瞄上我国2亿多台IoT设备

    恶意软件Mirai换了个马甲 瞄上我国2亿多台IoT设备   想要起来时,一种沉重感阻碍着他,这是一种安全感:感觉到一张床为他铺好了,而且只属于他:想要静卧时,一种不安阻碍着他,把他从床上赶起来,这是 ...

  5. .NET采集数据,放入数据库总结

    第一次做采集Json的还简单一些但是XML的简直了......... JSON //采集数据 public string GetBetRecordToRepository()//随便你返回什么 { t ...

  6. ARM总线方面知识

    AMBA简介 随着深亚微米工艺技术日益成熟,集成电路芯片的规模越来越大.数字IC从基于时序驱动的设计方法,发展到基于IP复用的设计方法,并在SOC设计中得到了广泛应用.在基于IP复用的SoC设计中,片 ...

  7. MongoDB查询分析

    MongoDB 查询分析可以确保我们建立的索引是否有效,是查询语句性能分析的重要工具.MongoDB 查询分析常用函数有:explain() 和 hint(). 1. explain(): 提供查询信 ...

  8. Single linked list by cursor

    有了指针实现看似已经足够了,那为什么还要有另外的实现方式呢?原因是诸如BASIC和FORTRAN等许多语言都不支持指针,如果需要链表而又不能使用指针,那么就必须使用另外的实现方法.还有一个原因,是在A ...

  9. 《mysql必知必会》读书笔记--存储过程的使用

    以前对mysql的认识与应用只是停留在增删改查的阶段,最近正好在学习mysql相关内容,看了一本书叫做<MySQL必知必会>,看了之后对MySQL的高级用法有了一定的了解.以下内容只当读书 ...

  10. Install a Jenkins on Ubuntu system

    ================================================================================ Jenkins Environment ...