Python: why visiting an existing attribute triggered "__getattr__"?

Tro*_*yvs -1 python getattr

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__,但是在调用它时无法识别。

Mar*_*ers 5

实现了__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实例。