__setattr__ только для имен, не найденных в атрибутах объекта`? - PullRequest
1 голос
/ 03 февраля 2012

Я хочу использовать __setattr__ только когда атрибут не был найден в атрибутах объекта, например __getattr__.

Действительно ли мне нужно использовать try-кроме ?

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

Ответы [ 3 ]

3 голосов
/ 03 февраля 2012

Вы можете использовать hasattr():

def __setattr__(self, name, value):
    if hasattr(super(Clazz, self), name):
        setattr(super(Clazz, self), name, value)
    else:
        # implement *my* __setattr__
        pass
0 голосов
/ 05 октября 2017

Во многих случаях вызов 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
0 голосов
/ 04 февраля 2012

__setattr__, если он существует, вызывается для каждого атрибута, установленного на объекте.

Ваш пример кода довольно смущает меня. Что вы пытаетесь сделать с заявлением: setattr(super(Clazz, self), name, value) ??

Установить атрибут для себя, при этом self рассматривается как экземпляр его суперкласса? Это не имеет смысла, потому что объект все еще "я".

С другой стороны, попытка использовать setattr для объекта, возвращаемого вызовом super, всегда приведет к ошибке атрибута, независимо от того, существует атрибут в суперклассе или нет. Это связано с тем, что super возвращает не сам суперкласс, а объект-обертку, который будет извлекать туда атрибуты, когда они необходимы - так что вы можете использовать hasattr в объекте, возвращаемом super, но не 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)
...