我知道在访问不存在的属性时会触发python的__getattr__
。
但在下面的示例中,在c1' s __init__
中,我创建了一个名为name的self属性。访问时,两种访问方式都触发了__getattr__
,因此打印了#34;无"。
这对我来说很奇怪。我想我的理解或代码都有问题吗?
$ cat n.py
class c1(object):
def __init__(s):
print 'init c1'
s.name='abc'
def __getattr__(s,name):
print "__getattr__:"+name
return None
def __setattr__(s,name,value):
print "__setattr__:"+value
def __get__(s,inst,owner):
print "__get__"
class d:
def __init__(s):
s.c=c1()
c=c1()
print c.name
o=d()
print o.c.name
$ python n.py
init c1
__setattr__:abc
__getattr__:name
None
init c1
__setattr__:abc
__getattr__:name
None
您可以在s.name='abc'
内看到我已定义__init__
,但在访问时无法识别。
答案 0 :(得分:4)
您还实施了__setattr__
,并且在尝试设置属性时始终被调用。您的版本仅打印属性:
def __setattr__(s,name,value):
print "__setattr__:"+value
,没有别的,这意味着该属性实际上不是 set 。上述内容是针对s.name='abc'
表达式调用的,name
属性从未设置,因此将来对name
属性的任何访问都会再次发送到__getattr__
。
让__setattr__
直接在__dict__
设置值:
def __setattr__(self, name, value):
print "__setattr__:" + value
self.__dict__[name] = value
或将您的课程设为new-style class(继承自object
),您可以使用super(c1, self).__setattr__(name, value)
重复使用基础实施。
作为旁注:您实施了c1.__get__
,大概是为了让班级成为descriptor object。但是,描述符协议仅适用于类属性,而不适用于实例属性,然后仅适用于新样式类。您的类d
不是新式类,并且您使用实例属性c
来存储c1
实例。