Bypassing __setattr__ for changing special attributes

Fuzzyman fuzzyman at gmail.com
Tue Feb 20 19:29:35 EST 2007


On Feb 20, 12:57 pm, Steven D'Aprano
<s... at REMOVE.THIS.cybersource.com.au> wrote:
> 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?
>

Magic attributes like __class__ are looked up on the class rather than
the instance.

Fuzzyman
http://www.voidspace.org.uk/python/articles.shtml

> --
> Steven.





More information about the Python-list mailing list