不少pythonic的代码都会用到内置方法,根据本身的经验,罗列一下本身知道的内置方法。python
这三个方法是字典类的内置方法,分别对应于查找、设置、删除操做,以一个简单的例子说明:闭包
class A(dict): def __getitem__(self, key): print '__getitem__' return super(A, self).__getitem__(key) def __setitem__(self, key, value): print '__setitem__' return super(A, self).__setitem__(key, value) def __delitem__(self, key): print '__delitem__' return super(A, self).__delitem__(key) a = A() a[1] = 1 b = a[1] del a[1] a.get(1)
上面的代码中a[1] = 1
实际上调用的就是a.__setitem__(1, 1)
, a[1]
调用的是a.__get__item__(1)
, del a[1]
调用的是a.__setitem__(1)
。须要注意的是,字典示例的get方法和__getitem__方法不存在调用关系,二者互不影响。函数
__getattribute__和__getattr__都是从python对象示例中获取成员变量的方法,差异在于__getattribute__在任什么时候候都会调用,而__getattr__只有在__getattribute__执行完成以后而且没有找到成员变量的时候才会执行。__setattr__在给成员变量赋值的时候调用,__delattr__在回收成员变量的时候调用,一下面的例子说明:code
class A(object): x = [] def __getattribute__(self, name): print '__getattribute__' return super(A, self).__getattribute__(name) def __setattr__(self, key, value): print '__setattr__' return super(A, self).__setattr__(key, value) def __getattr__(self, item): print '__getattr__' def __delattr__(self, item): print '__delattr__' return super(A, self).__delattr__(item) a = A() a.x a.y b = getattr(a, 'x') b = getattr(a, 'y') a.x = 1 a.y = 1 setattr(a, 'x', 1) setattr(a, 'y', 1) del a.x del a.y
由于x是a的成员变量,a.x会调用a.__getattribue__('x')
,而y不是a的成员变量,在调用a.__getattribue__('y')
以后还会调用a.__getattr__('y')
,内置方法getattr也是按照此顺序调用,惟一的区别在于getattr在成员变量不存在的时候不会抛出异常,而是给一个默认值。a.x = 1
和setattr(a, 'x', 1)
都会调用a.__setattr__('x', 1)
,若是原来的成员变量不存在,__setattr__会给实例增长一个成员变量,而不是抛出异常。对象
若是重载了__call__方法,则实例对象就能够像方法同样调用了。若是实例a的类实现了这个方法,那么a(*args, **kwargs)
就会调用a.__call__(*args, **kwargs)
。用这种方法能够简单方便的实现装饰器,以下所示:get
class A(object): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print '__call__' return self.func(*args, **kwargs) @A def foo(x): return x foo(1)
装饰器语法糖至关于foo = A(foo)
, 和闭包不一样,foo已经不是一个函数而是类A的实例。foo(1)
会执行foo.__call__(1)
。固然这个例子实现的装饰器并很差,会改变foo的函数签名,并且也不能装饰类方法。it
此外元类的__call__也能够控制实例的建立过程,由于当类建立对象时,元类的__call__函数就被调用,进而调用type.__call__建立对象,type.__call__回依次调用类的__new__和__init__生成实例。以单例模式为例:class
class Singleton(type): def __call__(cls, *args): print "Singleton call" if not hasattr(cls, 'instance'): cls.instance = super(Singleton, cls).__call__(*args) return cls.instance class Cache(object): __metaclass__ = Singleton def __new__(cls, *args): print "Cache new" return object.__new__(cls, *args) def __init__(cls, *args, **kwargs): print "Cache init" a = Cache() b = Cache() print a is b
这三个方法分别对应于描述器的查询、设置、删除函数,仍是以一个简单的例子来讲明:import
class A(object): def __get__(self, instance, owner): print '__get__' def __set__(self, instance, value): print '__set__' class B(object): a = A() b = B() c = b.a b.a = 1
类A的示例a做为b的成员变量时候,访问示例b中成员变量a的时候会调用a.__get__(b, B)
,修改b中成员变量a的时候会调用a.__set__(b, 1)
。须要注意的是,当用B.a访问的时候参数instance为None。实际上像classmethod,staticmethod这样的装饰器都是经过装饰器来实现的,经过装饰器就能够解决上面不能做为类方法装饰器的问题。变量
import types class Profiled(object): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): return self.func(*args, **kwargs) def __get__(self, instance, owner): if instance is None: return self else: return types.MethodType(self, instance) class Spam(object): @Profiled def bar(self, x): return x + 1 s = Spam() print s.bar(5)
在__get__方法中,不是Spam.bar调用,则instance不为None的状况下,会用types.MethodType把bar和s作一个绑定,s.bar(5)等价于执行了bar.__get__(s, Spam).__call__(5)
,看起来很绕,但实际上用起来很方便。