I knew that python's __getattr__ is triggered when visiting a non-existing attribute.
但是在下面的示例中,在 c1's 中__init__,我创建了一个名为 name 的 self 属性。访问它时,两种访问方式都触发__getattr__并因此打印“无”。
这对我来说很奇怪。我想我的理解或我的代码有问题吗?
$ 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
Run Code Online (Sandbox Code Playgroud)
你可以看到我已经s.name='abc'在里面定义了__init__,但是在调用它时无法识别。
您还实现了__setattr__,并且在尝试设置属性时总是会调用它。您的版本只打印属性:
def __setattr__(s,name,value):
print "__setattr__:"+value
Run Code Online (Sandbox Code Playgroud)
仅此而已,这意味着该属性实际上并未设置。上面是为s.name='abc'表达式调用的,该name属性从未设置,因此将来对该name属性的任何访问都会__getattr__再次发送。
已__setattr__设置的值__dict__可以直接使用:
def __setattr__(self, name, value):
print "__setattr__:" + value
self.__dict__[name] = value
Run Code Online (Sandbox Code Playgroud)
或者使您的类成为新式类(继承自object),并且您可以使用super(c1, self).__setattr__(name, value).
附带说明:您实现了c1.__get__,大概是为了使类成为描述符对象。但是,描述符协议仅适用于类属性,不适用于实例属性,然后仅适用于新型类。您的类d不是新式类,并且您使用了实例属性c来存储c1实例。
| 归档时间: |
|
| 查看次数: |
254 次 |
| 最近记录: |