Python:为什么要访问现有属性" __ getattr __"?

时间:2016-11-30 14:40:42

标签: python getattr

我知道在访问不存在的属性时会触发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__,但在访问时无法识别。

1 个答案:

答案 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实例。