Bypassing __setattr__ for changing special attributes
Steven D'Aprano
steve at REMOVE.THIS.cybersource.com.au
Tue Feb 20 07:57:34 EST 2007
On Mon, 19 Feb 2007 23:18:02 -0800, Ziga Seilnacht wrote:
> George Sakkis wrote:
>> I was kinda surprised that setting __class__ or __dict__ goes through
>> the __setattr__ mechanism, like a normal attribute:
>>
>> class Foo(object):
>> def __setattr__(self, attr, value):
>> pass
>>
>> class Bar(object):
>> pass
>>
>> >>> f = Foo()
>> >>> f.__class__ = Bar
>> >>> print f.__class__ is Foo
>> True
>>
>> Is there a way (even hackish) to bypass this, or at least achieve
>> somehow the same goal (change f's class) ?
>>
>> George
>
>>>> object.__setattr__(f, '__class__', Bar)
>>>> f.__class__ is Bar
> True
This version is arguably more "correct", although a tad longer to write,
and doesn't need you to hard-code the class superclass:
super(f.__class__, f).__setattr__('__class__', Bar)
But what surprised me was that this *didn't* work:
>>> f = Foo()
>>> f.__dict__['__class__'] = Bar
>>> f.__class__
<class '__main__.Foo'>
Unless I'm confused, it looks like instance.__class__ bypasses the usual
lookup mechanism (instance.__dict__, then instance.__class__.__dict__) for
some reason.
>>> Foo.x = 1 # stored in class __dict__
>>> f.x
1
>>> f.__dict__['x'] = 2 # stored in instance __dict__
>>> f.x
2
>>> Foo.x
1
But __class__ doesn't behave like this. Why?
--
Steven.
More information about the Python-list
mailing list