python2的类分为经典类和新式类,派生自object的类都是新式类,python3的类都是新式类,默认派生自object。python2的__get__、 __getattr__、 __getatrribute__函数和python3的略有不同,下面分点说明。
1.__get__(self, instance, owner)
__get__(self, instance, owner)函数只有在新式类中有意义,在经典类中无意义。在新式的class中,如果定义了__get__,则这个类可以成为descriptor。owner为把descriptor设为类属性的class, instance为该class的实例。如果通过class访问descriptor,则instance为None。
测试代码如下图所示,左中右分别为python2经典类、python2新式类、python3的类:
有图可以看出,__get__在python2经典类中无意义,在python2新式类中和python3的意义一样。
2.__getattr__(self, attr)、 __getatrribute__(self, attr)
(1)经典类中的__getattr__,__getatrribute__
__getatrribute__函数在经典类中无意义,__getattr__函数在经典类中有意义。测试代码如下。
>>> class A:
def __init__(self, x):
self.x = x
def __getattr__(self, attr):
return 'getattr: ', attr
>>> class B:
def __init__(self, x):
self.x = x
def __getattribute__(self, attr):
return 'getattribute: ', attr
>>> a = A('foo'); b = B('bar')
>>>
>>> a.x
'foo'
>>> b.x
'bar'
>>> a.y
('getattr: ', 'y')
>>> b.y
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
b.y
AttributeError: B instance has no attribute 'y'
>>>
(2)新式类中的__getattr__,__getatrribute__
同时定义了__getattr__和__getattribute__的话,访问类实例属性只会调用__getattribute__,不管该属性是否存在。只定义了__getattr__没有定义__getattribute__的情况下,访问存在的类实例属性不会调用__getattr__,会返回该属性的值;访问不存在的实例属性的话会调用__getattr__。测试代码见下图,左边为python2新式类,右边为python3.