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 作为第一个参数

 

posted @ 2019-02-14 17:30  jj千寻  阅读(177)  评论(0编辑  收藏  举报