Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #66206

Re: Using a subclass for __dict__

From Peter Otten <__peter__@web.de>
Subject Re: Using a subclass for __dict__
Date 2014-02-13 20:10 +0100
Organization None
References <CAE+T62bYFSdYmYRbY1Cuz51zym-NMYv0O5CnJvsbTR41oUZsag@mail.gmail.com>
Newsgroups comp.lang.python
Message-ID <mailman.6855.1392318635.18130.python-list@python.org> (permalink)

Show all headers | View raw


Demian Brecht wrote:

> Using bases in a metaclass, I've been able to easily figure out when
> an attribute is being added to an instance of a class. However, what
> I'm /actually/ looking to do is to intercept when attributes are being
> added to a class (not an instance of). I thought that I'd be able to
> do so by passing in a subclass of dict to type.__new__ of the
> metaclass's __new__ and implementing a custom __setitem__, but
> apparently that's not the case.
> 
> If you're curious as to why I'm doing this, I'm trying to clean up
> https://gist.github.com/demianbrecht/6944269 and get rid of the
> late_bind method there in favour of using the appropriate magic
> methods. The intention is to piggyback off of abc's
> __abstractmethods__ in order to implement a "looks_like" method that
> checks that one class conforms to an unrelated class's interface
> rather than using inheritance to enforce interface implementations at
> class creation time. This is /only/ intended to be a proof of concept
> for demonstration purposes and nothing that I'd ever actually
> implement, so no need for flaming the concept :)
> 
> # test.py
> 
> class Dict(dict):
>     def __setattr__(self, key, value):
>         print 'Dict.__setattr__'
>         dict.__setattr__(self, key, value)
> 
>     def __setitem__(self, key, value):
>         print 'Dict.__setitem__'
>         dict.__setitem__(self, key, value)
> 
> class Bar(object):
>     def __setattr__(self, key, value):
>         print 'Bar.__setattr__'
>         object.__setattr__(self, key, value)
> 
> class metafoo(type):
>     def __new__(mcls, name, bases, dct):
>         return type.__new__(mcls, name, (Bar,), Dict(dct))
> 
> class Foo(object):
>     __metaclass__ = metafoo
> 
>>>> import test
>>>> f = test.Foo()
>>>> f.foo = 'bar'
> Bar.__setattr__ # expected
>>>> test.Foo.foo = 'bar'
> # I'm expecting Dict.__setattr__ here, but... *crickets*
> 
> Am I missing something here, or do I just have to live with what I
> currently have in my gist?

I don't really understand what you are trying to do in the gist, perhaps you want

<http://docs.python.org/dev/reference/datamodel.html#customizing-instance-and-subclass-checks>

?

Anyway, intercepting __setattr__() in the class becomes easy once you remember that a class is just 
an instance of its metaclass:

>>> class FooMeta(type):
...     def __setattr__(self, name, value):
...             print value, "-->", name
...             super(FooMeta, self).__setattr__(name, value)
... 
>>> class Foo:
...     __metaclass__ = FooMeta
... 
>>> Foo.bar = "baz"
baz --> bar

Python 3 has a bit more to offer in this area, see

<http://docs.python.org/dev/reference/datamodel.html#preparing-the-class-namespace>

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: Using a subclass for __dict__ Peter Otten <__peter__@web.de> - 2014-02-13 20:10 +0100

csiph-web