属性访问,首先要区分类属性和实例属性。可以用__dict__方法来查看。
比如:
class A(object):
name = "unchange." #类属性
def __init__(self):
self.value = 10 #实例属性
a = A()
print a.__dict__
# {'value': 10}
print A.__dict__
# {'__module__': '__main__', 'name': 'unchange.',
# '__dict__': <attribute '__dict__' of 'A' objects>,
# '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None,
# '__init__': <function __init__ at 0x000000000225EB38>}
类属性的访问顺序是从当前类到父类、基类一直往上搜索,直到存在这个属性,若不存在则抛错。
下面给例子说明实例属性和类属性的关系以及实例属性的访问顺序。
class A(object):
name = "unchange."
def __init__(self):
self.value = 10
def __getattribute__(self, item):
print "into __getattribute__"
return object.__getattribute__(self, item)
a = A()
print a.__dict__
# {'value': 10}
print a.name
# into __getattribute__
# unchange.
print A.__dict__
# {'__module__': '__main__', 'name': 'unchange.',
# '__getattribute__': <function __getattribute__ at 0x000000000229EBA8>,
# '__dict__': <attribute '__dict__' of 'A' objects>,
# '__weakref__': <attribute '__weakref__' of 'A' objects>
# , '__doc__': None, '__init__': <function __init__ at 0x000000000229EB38>}
当访问实例属性a.name时,其访问顺讯是:(假设没有数据描述符)
先进入__getattribute__
1、实例属性a.__dict__ 2、类属性A.__dict__ 3、父类及基类属性A.__bases__.__dict
搜索不到再进入__getattr__
如果实例属性a.__dict__存在这个属性,就不据需往下搜索了
class A(object):
name = "unchange."
def __init__(self):
self.value = 10
def __getattribute__(self, item):
print "into __getattribute__"
return object.__getattribute__(self, item)
a = A()
a.name = "change"
print a.__dict__
# {'name': 'change', 'value': 10}
print a.name
# into __getattribute__
# change
print A.name
# unchange.
基类属性A.name和实例属性值不同,在实例__dict__中找到后,就不去类A得到__dict__找了。
a.name = "change" 这个赋值方式 等效于a.__dict__['name'] = "change"
实例属性是这实例独有的,类属性是所有实例共有的。
两个不同的实例,内存空间互相独立,所以各自实例属性也是独立的。