【问题标题】:__setattr__ only for names not found in the object's attributes`?__setattr__ 仅适用于在对象属性中找不到的名称?
【发布时间】:2012-02-03 18:12:28
【问题描述】:

我只想在对象的属性中找不到该属性时才使用__setattr__,例如__getattr__

我真的必须使用 try-except 吗?

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

【问题讨论】:

  • 好吧,你可以使用if hasattr()...
  • 好吧,文档对此非常明确......还有什么要问的?
  • 你可以为你做一个装饰器

标签: python getattr setattr


【解决方案1】:

你可以使用hasattr():

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

【讨论】:

  • “super”返回的对象中的 setattr 不起作用。完全没有。 “super”返回一个特殊的惰性求值对象,它从超类而不是实际的超类中检索属性。
  • (正如您在我的回答中看到的那样,使用super(...).__setattr__(...) 有效,而不是setattr(super(...), ...)
【解决方案2】:

__setattr__,如果存在,则为对象上设置的每个属性调用。

不过,您的示例代码让我很困惑。你想对声明做什么: setattr(super(Clazz, self), name, value)??

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

另一方面,尝试在调用“super”返回的对象上使用“setattr”总是会产生属性错误,无论该属性是否存在于超类中。那是因为 super 返回的不是超类本身,而是一个包装器对象,它会在需要时从那里获取属性 - 因此您可以在 super 返回的对象中使用“hasattr”,但不能使用 setattr。我以为它会这样,就在控制台上试了一下:

>>> 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)

【讨论】:

  • 时间不多,稍后再看,谢谢您的回答。但是setattr(obj, name, value) 等于obj.__setattr__(name, value)
  • 不是当你的“obj”是对“super”的调用时,如上所示。
【解决方案3】:

很多时候调用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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 2013-03-16
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多