2012-02-03 4 views
1

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

Нужно ли мне использовать try-except?

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

Ну, вы можете использовать 'if hasattr()' ... – kindall

+0

Ну, документация довольно подробно об этом ... что еще спросить? – delnan

+0

Вы можете сделать декоратор, чтобы сделать это за вас – jterrace

ответ

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» возвращает специальный ленивый объект оценки, который извлекает атрибуты из суперкласса, а не фактический суперкласс. – jsbueno

+0

(как вы можете видеть в моем ответе, используя 'super (...) .__ setattr __ (...)' работает, хотя, в отличие от 'setattr (super (...), ...)' – jsbueno

0

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

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

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

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

Not много времени, посмотрим на это позже, спасибо за ваш ответ, но 'setattr (obj, name, value)' равно 'obj .__ setattr __ (name, value)'. –

+0

Не когда ваш «obj» является вызовом «супер», как показано выше. – jsbueno

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