python的特殊方法(魔术方法)

特殊方法:

又名魔术方法,所有双下划线开头双下划线结尾的方法

  1. 构造函数,析构函数,__call__
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Meta(type):
    def __new__(meta_class, name, bases, attrs):
        # 这里主要是为了获取name, bases, attrs这三个东西,便于做进一步的处理
        cls = super(Meta, meta_class).__new__(meta_class, name, bases, attrs)
        print cls  # 
        print meta_class  # 
        print name  # FOO
        print bases  # (,)
        print attrs  # {'demo': , '__module__': '__main__', '__metaclass__': , '__new__': }
        # 可以在这里做很多 针对cls的操作
        cls.a = 'herehere'
        return cls
    def __init__(cls, name, bases, attrs):
        print cls, name, bases, attrs
    def __call__(cls, *args, **kwargs):
        self = cls.__new__(cls, *args, **kwargs)
        if isinstance(self, cls):
            self.__init__(*args, **kwargs)
            return self
class Base(object):
    pass
class FOO(Base):
    __metaclass__ = Meta
    def __new__(cls, *args, **kwargs):
        # 返回值是FOO的实例,例如,return 'aaa',那么print FOO(1, 2, 3)的输出就是aaa
        print args
        return object.__new__(cls)
    def __init__(self, *args, **kwargs):
        pass
    def demo(self):
        pass
    def __del__(self):
        pass
foo = FOO(1, 2, 3)
print foo.a # herehere
  1. 属性控制
    __setattr__
    __getattr__
    __delattr__
    __getattribute__ :本方法定义了对象对属性的获取顺序。
def __setattr__(self, name, value):
    self.name = value
    #每当属性被赋值的时候, "__setattr__()" 会被调用,这样就造成了递归调用。
    #这意味这会调用 "self.__setattr__('name', value)" ,每次方法会调用自己。这样会造成程序崩溃。
def __setattr__(self, name, value):
    self.__dict__[name] = value  #给类中的属性名分配值
    #定制特有属性
  1. 创建定制的序列,(可迭代对象等)
    现在我们开始讲如何在Python中创建定制的序列,这个时候该讲一讲协议。
    协议(Protocols)与其他语言中的接口很相似。它给你很多你必须定义的方法。然而在Python中的协议是很不正式的,不需要明确声明实现。事实上,他们更像一种指南。
    a) 实现不可变容器,你只能定义 __len__ 和 __getitem__
    b) 可变容器协议则需要所有不可变容器的所有另外还需要 __setitem__ 和 __delitem__。
    c) 如果你希望你的对象是可迭代的话(可迭代对象),你需要定义 __iter__会返回一个迭代器。
    d) 迭代器必须遵循迭代器协议,需要有 __iter__ (返回它本身) 和 __next__ 。
__getitem__(self, key) 定义当一个条目被访问时,使用符号 self[key] 
__setitem__(self, key, value) 定义当一个条目被赋值时的行为,使用 self[key] = value
__delitem__(self, key) 定义当一个条目被删除时的行为(比如 del self[key])
__iter__(self) 返回一个容器的迭代器,尤其是当内置的 iter() 方法被调用的时候,或者当使用 for x in container 方式循环的时候。迭代器是他们本身的对象,他们必须定义返回 self 的 __iter__ 方法
__reversed__(self) 实现当 reversed() 被调用时的行为
__contains__(self, item) 当调用 in 和 not in 来测试成员是否存在时候 __contains__ 被定义,当 __contains__ 没有被定义的时候,Python会迭代这个序列并且当找到需要的值时会返回 True 。__concat__(self, other) 和 + 操作符相关
  1. 上下文管理器(会话管理)
    with 管理的上下文实际上就是Closer,Closer是一个类(也是命名空间),这个命名空间提供了两个大门,一个前门(enter),一个后门exit。上下文管理器可以自动捕获异常,除此之外,在没有别的特别的地方了。
class Closer(object):
def __init__(self, obj):
        self.obj = obj #'obj'
    def __enter__(self):
        return self.obj #conn
    def __exit__(self, exception_type, exception_val, trace):
        try:
            print 'im here'
            print exception_type, exception_val, trace
        except AttributeError:
            print 'Not closable.'
        return True #处理conn.dir()引起的异常,如果返回True,并不会将异常向上级发送。
with Closer('obj') as conn:
    print conn
    raise Exception('exception info')
print conn
print 'out of context management'
  1. 描述符
    描述符能够让一个属性变成一个方法,使python对属性的读写有更多的逻辑控制,描述符的优先级非常高~
    python对属性的搜索优先级
class Meter(object):
    '''Descriptor for a meter.'''
    def __init__(self, value=3):
        self.value = float(value)
    def __get__(self, instance, owner):
        print instance.attr_demo # instance_attr
        print owner.attr_demo # class_attr
        return self.value
    def __set__(self, instance, value):
        self.value = float(value)
class Foot(object):
    '''Descriptor for a foot.'''
    def __get__(self, instance, owner):
        return instance.meter * 3.2808
    def __set__(self, instance, value):
        instance.meter = float(value) / 3.2808
class Distance(object):
    '''Class to represent distance holding two descriptors for feet and
    meters.'''
    attr_demo = 'class_attr'
    meter = Meter()
    foot = Foot()
distance_instance_demo = Distance()
distance_instance_demo.attr_demo = 'instance_attr'
print distance_instance_demo.meter # 3.0
print distance_instance_demo.foot # 9.8424
  1. __index__
class IndexHash(object):
    def __index__(self):
        return 1
index_hash = IndexHash()
list_demo = ['abc', 'def', 'ghi']
print list_demo[index_hash] # 'def'
魔术方法 调用方式 解释
new(cls [,...]) instance = MyClass(arg1, arg2) new 在创建实例的时候被调用
init(self [,...]) instance = MyClass(arg1, arg2) init 在创建实例的时候被调用
cmp(self, other) self == other, self > other, 等。 在比较的时候调用
pos(self) +self 一元加运算符
neg(self) -self 一元减运算符
invert(self) ~self 取反运算符
index(self) x[self] 对象被作为索引使用的时候
nonzero(self) bool(self) 对象的布尔值
getattr(self, name) self.name # name 不存在 访问一个不存在的属性时
setattr(self, name, val) self.name = val 对一个属性赋值时
delattr(self, name) del self.name 删除一个属性时
__getattribute(self, name) self.name 访问任何属性时
getitem(self, key) self[key] 使用索引访问元素时
setitem(self, key, val) self[key] = val 对某个索引值赋值时
delitem(self, key) del self[key] 删除某个索引值时
iter(self) for x in self 迭代时
contains(self, value) value in self, value not in self 使用 in 操作测试关系时
concat(self, value) self + other 连接两个对象时
call(self [,...]) self(args) “调用”对象时
enter(self) with self as x: with 语句环境管理
exit(self, exc, val, trace) with self as x: with 语句环境管理
getstate(self) pickle.dump(pkl_file, self) 序列化
setstate(self) data = pickle.load(pkl_file) 序列化

你可能感兴趣的:(python的特殊方法(魔术方法))