python-魔法方法
http://blog.51cto.com/leejia/2132061?source=dra
构造方法
1.__init__:指明一个对象初始化的行为,它获取任何传给构造器的参数
2.调用x = SomeClass()
的时候, __init__
并不是第一个被调用的方法,事实上,第一个被调用的是 __new__
3.对象的生命周期结束的时候, __del__
会被调用
比较
__eq__(self, other)
定义等于操作符(==)的行为。
def __eq__(self, other): # 定义内置方法 ,判定类相等
return self.__dict__ == other.__dict__ # 判断的是两对象空间的属性值是否相等
__ne__(self, other)
定义不等于操作符(!=)的行为。
__lt__(self, other)
定义小于操作符(<)的行为。
__gt__(self, other)
定义大于操作符(>)的行为。
__le__(self, other)
定义小于等于操作符(<)的行为。
__ge__(self, other)
定义大于等于操作符(>)的行为。
一元操作
__pos__(self)
实现取正操作,例如 +some_object
。
__neg__(self)
实现取负操作,例如 -some_object
。
__abs__(self)
实现内建绝对值函数 abs()
操作。
__invert__(self)
实现取反操作符 ~
。
__round__(self, n)
实现内建函数 round()
,n 是近似小数点的位数。
__floor__(self)
实现 math.floor()
函数,即向下取整。
__ceil__(self)
实现 math.ceil()
函数,即向上取整。
__trunc__(self)
实现 math.trunc()
函数,即距离零最近的整数。
算数操作
__add__(self, other)
实现加法操作。
__sub__(self, other)
实现减法操作。
__mul__(self, other)
实现乘法操作。
__floordiv__(self, other)
实现使用 //
操作符的整数除法。
__div__(self, other)
实现使用 /
操作符的除法。
__truediv__(self, other)
实现 _true_
除法,这个函数只有使用 from __future__ import division
时才有作用。
__mod__(self, other)
实现 %
取余操作。
__divmod__(self, other)
实现 divmod
内建函数。
__pow__
实现 **
操作符。
__lshift__(self, other)
实现左移位运算符 <<;
。
__rshift__(self, other)
实现右移位运算符>> 。
__and__(self, other)
实现按位与运算符 &
。
__or__(self, other)
实现按位或运算符 |
。
__xor__(self, other)
实现按位异或运算符 ^
。
反射算数运算
some_object + other:是“常见”的加法;
反射是一样的意思,只不过是运算符交换了一下位置:other + some_object;
__radd__(self, other)
实现反射加法操作。
__rsub__(self, other)
实现反射减法操作。
__rmul__(self, other)
实现反射乘法操作。
__rfloordiv__(self, other)
实现使用 //
操作符的整数反射除法
.............
增强赋值运算
a += b
__iadd__(self, other)
实现加法赋值操作。
__isub__(self, other)
实现减法赋值操作。
..........
类型转换操作
__int__(self)
实现到int的类型转换。
__long__(self)
实现到long的类型转换。
__float__(self)
实现到float的类型转换。
__complex__(self)
实现到complex的类型转换。
__oct__(self)
实现到八进制数的类型转换。
__hex__(self)
实现到十六进制数的类型转换。
类的表示
__str__(self)
定义对类的实例调用 str()
时的行为, 产生人类可读的输出。
__repr__(self)
repr() 函数将对象转化为供解释器读取的形式,产生机器可读的输出(大部分情况下,其输出可以作为有效的Python代码)。
访问控制
__getattr__(self, name)
当用户试图访问一个根本不存在(或者暂时不存在)的属性时,你可以通过这个魔法方法来定义类的行为。这个可以用于捕捉错误的拼写并且给出指引,使用废弃属性时给出警告,只有当试图访问不存在的属性时它才会被调用,所以这不能算是一个真正的封装的办法。
__setattr__(self, name, value)
它允许你自定义某个属性的赋值行为。
__delattr__(self, name)
这个魔法方法和 __setattr__
几乎相同,只不过它是用于处理删除属性时的行为。
使用注意
def __setattr__(self, name. value):
self.name = value
# 因为每次属性幅值都要调用 __setattr__(),所以这里的实现会导致递归
# 这里的调用实际上是 self.__setattr('name', value)。因为这个方法一直
# 在调用自己,因此递归将持续进行,直到程序崩溃
#正确形式
def __setattr__(self, name, value):
self.__dict__[name] = value # 使用 __dict__ 进行赋值
# 定义自定义行为
自定义序列
可以让你的Python类表现得像是内建序列类型(字典,元组,列表,字符串等)
Python中实现自定义容器类型需要用到一些协议。
首先,不可变容器类型有如下协议:想实现一个不可变容器,你需要定义 __len__
和 __getitem__
(后面会具体说明)。可变容器的协议除了上面提到的两个方法之外,还需要定义 __setitem__
和 __delitem__
。最后,如果你想让你的对象可以迭代,你需要定义 __iter__
,这个方法返回一个迭代器。迭代器必须遵守迭代器协议,需要定义 __iter__
(返回它自己)和 next
方法。
__len__(self)
返回容器的长度,可变和不可变类型都需要实现。
__getitem__(self, key)
定义对容器中某一项使用 self[key]
的方式进行读取操作时的行为。这也是可变和不可变容器类型都需要实现的一个方法。它应该在键的类型错误式产生 TypeError
异常,同时在没有与键值相匹配的内容时产生 KeyError
异常。
__setitem__(self, key)
定义对容器中某一项使用 self[key]
的方式进行赋值操作时的行为。它是可变容器类型必须实现的一个方法,同样应该在合适的时候产生 KeyError
和 TypeError
异常。
__iter__(self, key)
它应该返回当前容器的一个迭代器。迭代器以一连串内容的形式返回,最常见的是使用 iter()
函数调用,以及在类似 for x in container:
的循环中被调用。迭代器是他们自己的对象,需要定义 __iter__
方法并在其中返回自己。
__reversed__(self)
定义了对容器使用 reversed()
内建函数时的行为。它应该返回一个反转之后的序列。当你的序列类是有序时,类似列表和元组,再实现这个方法,
__contains__(self, item)
定义了使用 in
和 not in
进行成员测试时类的行为。你可能好奇为什么这个方法不是序列协议的一部分,原因是,如果 __contains__
没有定义,Python就会迭代整个序列,如果找到了需要的一项就返回 True
。
__missing__(self ,key)
它定义了当试图访问一个字典中不存在的键时的行为(目前为止是指字典的实例,例如我有一个字典 d
, "george"
不是字典中的一个键,当试图访问 d["george']
时就会调用 d.__missing__("george")
)
例子:实现了一些函数式结构的列表
class FunctionalList:
'''一个列表的封装类,实现了一些额外的函数式
方法,例如head, tail, init, last, drop和take。'''
def __init__(self, values=None):
if values is None:
self.values = []
else:
self.values = values
def __len__(self):
return len(self.values)
def __getitem__(self, key):
# 如果键的类型或值不合法,列表会返回异常
return self.values[key]
def __setitem__(self, key, value):
self.values[key] = value
def __delitem__(self, key):
del self.values[key]
def __iter__(self):
return iter(self.values)
def __reversed__(self):
return reversed(self.values)
def append(self, value):
self.values.append(value)
def head(self):
# 取得第一个元素
return self.values[0]
def tail(self):
# 取得除第一个元素外的所有元素
return self.valuse[1:]
def init(self):
# 取得除最后一个元素外的所有元素
return self.values[:-1]
def last(self):
# 取得最后一个元素
return self.values[-1]
def drop(self, n):
# 取得除前n个元素外的所有元素
return self.values[n:]
def take(self, n):
# 取得前n个元素
return self.values[:n]
反射
__instancecheck__(self, instance)
检查一个实例是否是你定义的类的一个实例(例如 isinstance(instance, class)
)。
__subclasscheck__(self, subclass)
检查一个类是否是你定义的类的子类(例如 issubclass(subclass, class)
)。
上下文管理器
with open('foo.txt') as bar:
# 使用bar进行某些操作
with
声明创建时,上下文管理器允许类做一些设置和清理工作。上下文管理器的行为由下面两个魔法方法所定义:
__enter__(self)
定义使用 with
声明创建的语句块最开始上下文管理器应该做些什么。 __enter__
的返回值会赋给 with
声明的目标,也就是 as
之后的名字。
__exit__(self, exception_type, exception_value, traceback)
定义当 with
声明语句块执行完毕(或终止)时上下文管理器的行为。它可以用来处理异常,进行清理,或者做其他应该在语句块结束之后立刻执行的工作。如果语句块顺利执行, exception_type
, exception_value
和 traceback
会是 None
。否则,你可以选择处理这个异常或者让用户来处理。如果你想处理异常,确保 __exit__
在完成工作之后返回 True
拷贝
copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
copy.deepcopy 深拷贝 拷贝对象及其子对象
__copy__(self)
返回一个对象的浅拷贝,这意味着拷贝出的实例是全新的,然而里面的数据全都是引用的。也就是说,对象本身是拷贝的,但是它的数据还是引用的(所以浅拷贝中的数据更改会影响原对象)。
__deepcopy__(self, memodict=)
实例使用 copy.deepcopy()
时的行为。 copy.deepcopy()
返回一个对象的深拷贝,这个对象和它的数据全都被拷贝了一份。当你想深拷贝一个单独的属性时,在那个属性上调用 copy.deepcopy()
,使用 memodict
作为第一个参数