質問

I want to use __setattr__ only when the attribute was not found in the object's attributes, like __getattr__.

Do I really have to use try-except?

def __setattr__(self, name, value):
    try:
        setattr(super(Clazz, self), name, value)
    except AttributeError:
        # implement *my* __setattr__
        pass
役に立ちましたか?

解決

You can use hasattr():

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

他のヒント

__setattr__, if it exists, is called for every attribute set on the object.

Your example code, though, is rather confusing for me. What are you trying to do with the statement: setattr(super(Clazz, self), name, value) ??

Set an attribute on self, with self viewed as an instance of its superclass? That makes no sense, because the object is still "self".

On the other hand trying to use "setattr" on the object returned by a call to "super" will always yield an attribute error, regardless if the attribute exists on the superclass or not. That is because super returns not the superclass itself, but a wrapper object that wil fetch attributes there when they are needed - so you can use "hasattr" in the object returned by super, but not setattr. I thought it would behave so, and just tried it on the console :

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

But then, you can just use "hasattr" in the object itself, and proceed like this:

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)

There are many times when calling hasattr won't work the way you expect (e.g., you've overridden __getattr__ to always return a value), so another way to set the right attribute in the right place would be something like this:

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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top