时间:2021-07-01 10:21:17 帮助过:29人阅读
Python是一个完全面向对象的语言。不仅实例是对象,类,函数,方法也都是对象。
所谓“定义一个函数”,实际上也就是生成一个函数对象。而“定义一个方法”就是生成一
个函数对象,并把这个对象放在一个类的__dict__中。下面两种定义方法的形式是等价的:
>>> print Foo.qux, Foo.__dict__['qux']
>>> foo = Foo()
>>> foo.bar()
2
>>> foo.qux()
3
而类继承就是简单地定义两个类对象,各自有不同的__dict__:
复杂的地方在`.`这个运算符上。对于类来说,Stilton.taste的意思是“在Stilton.__dict__中找'taste'. 如果没找到,到父类Cheese的__dict__里去找,然后到父类的父类,等等。如果一直到object仍没找到,那么扔一个AttributeError.”
实例同样有自己的__dict__:
不管__init__()是在哪儿定义的, stilton.__dict__与类的__dict__都无关。
Cheese.weight和Stilton.weight都会出错,因为这两个都碰不到实例的命名空间。而
stilton.weight的查找顺序是stilton.__dict__ => Stilton.__dict__ =>
Cheese.__dict__ => object.__dict__. 这与Stilton.taste的查找顺序非常相似,仅仅是
在最前面多出了一步。
方法稍微复杂些。
>>> print Cheese.get_weight
>>> print stilton.get_weight
<__main__.Stilton object at 0x7ff820669190>>
getattr(stilton, 'weight')和stilton.weight是等价的。类对象和实例对象没有本质区别,getattr(Cheese, 'smell')和Cheese.smell同样是等价的。getattr()与点运算符相比,好处是属性名用字符串指定,可以在运行时改变。
__getattribute__()是最底层的代码。如果你不重新定义这个方法,object.__getattribute__()和type.__getattribute__()就是getattr()的具体实现,前者用于实例,后者用以类。换句话说,stilton.weight就是object.__getattribute__(stilton, 'weight'). 覆盖这个方法是很容易出错的。比如说点运算符会导致无限递归:
__getattr__()是在__dict__查找没找到的情况下调用的方法。一般来说动态生成属性要用这个,因为__getattr__()不会干涉到其它地方定义的放到__dict__里的属性。
>>> print stilton.get_weight()
100g
>>> print stilton.age
Traceback (most recent call last):
File "", line 1, in
File "", line 12, in __getattr__
AttributeError: age
希望本文所述对大家的Python程序设计有所帮助。