2012-02-03 44 views
1

仅当在对象的属性中找不到该属性时,才想使用__setattr__,如__getattr____setattr__仅适用于在对象属性中找不到的名称?

难道我真的要用试试 - 除了

def __setattr__(self, name, value): 
    try: 
     setattr(super(Clazz, self), name, value) 
    except AttributeError: 
     # implement *my* __setattr__ 
     pass 
+0

那么,你可以使用'如果hasattr()'... – kindall 2012-02-03 18:14:36

+0

那么,文档相当明确...还有什么要问? – delnan 2012-02-03 18:14:37

+0

你可以让一个装饰器为你做 – jterrace 2012-02-03 18:17:26

回答

3

您可以使用hasattr()

def __setattr__(self, name, value): 
    if hasattr(super(Clazz, self), name): 
     setattr(super(Clazz, self), name, value) 
    else: 
     # implement *my* __setattr__ 
     pass 
+0

由“super”返回的对象中的setattr不起作用。完全一样。 “super”返回一个特殊的懒惰评估对象,它从超类中检索属性,而不是实际的超类。 – jsbueno 2012-02-04 02:36:41

+0

(正如你可以在我的答案中看到的,使用'super(...).__ setattr __(...)'工作,但与'setattr(super(...),...)'相反' – jsbueno 2012-02-04 02:50:31

0

__setattr__,如果存在的话,被称为该对象上设置每个属性。

尽管如此,您的示例代码对我来说相当困惑。你想要做什么与声明: setattr(super(Clazz, self), name, value) ??

在self上设置一个属性,并将self视为其超类的一个实例?这没有意义,因为对象仍然是“自我”。

另一方面,试图对由“super”调用返回的对象使用“setattr”将始终产生属性错误,无论该属性是否存在于超类中。这是因为super不是超类本身,而是一个包装对象,它在需要的时候获取属性 - 所以你可以在由super返回的对象中使用“hasattr”,但不能在setattr中使用“hasattr”。我认为它会表现得如此,只是试了一下在控制台上:

>>> class A(object):pass 
... 
>>> class B(A): pass 
... 
>>> b = B() 
>>> super(B,b) 
<super: <class 'B'>, <B object>> 
>>> setattr(super(B,b), "a", 5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'super' object has no attribute 'a' 
>>> A.a = 1 
>>> setattr(super(B,b), "a", 5) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'super' object has no attribute 'a' 

但是,你可以只使用“hasattr”的对象本身,然后像这样:

def __setattr__(self, attr, value): 
    if hasattr(self, value): 
     #this works because retrieving "__setattr__" from the 
     # result of the supercall gives the correct "__setattr__" of the superclass. 
     super(Clazz, self).__setattr__(self, attr, value) 
    else: 
     # transform value /or attribute as desired in your code 
     super(Clazz, self).__setattr__(self, attr, value) 
+0

但是'setattr(obj,name,value)'等于'obj .__ setattr __(name,value)'。 – 2012-02-04 08:31:59

+0

不是当你的“obj”是一个调用的时候, “超级”,如上所示。 – jsbueno 2012-02-05 02:20:07

0

有很多时候拨打电话hasattr将无法​​按照您期望的方式工作(例如,您已重写__getattr__以始终返回值),因此在正确的位置设置正确属性的另一种方式将如下所示:

def __setattr__(self, k, v): 
    if k in self.__dict__ or k in self.__class__.__dict__: 
     super(Clazz, self).__setattr__(k, v) 
    else: 
     # implement *my* __setattr__ 
     pass 
相关问题