properties and formatting with self.__dict__
Andrew Bennetts
andrew-pythonlist at puzzling.org
Fri Feb 21 22:10:51 EST 2003
On Fri, Feb 21, 2003 at 07:56:40PM +0000, Alex Martelli wrote:
> <posted & mailed>
>
> Andrew Bennetts wrote:
> ...
> >> > You should write in the __init__ method something like
> >> >
> >> > "self.full_name=property(self.get_full_name)"
> ...
> >> Except that, unfortunately, properties won't work as instance
> >> attributes,
> >> only as class attributes.
> >
> > I think you could fairly easily write your own instanceproperty that did
> > work with instances, though.
>
> Could you? Maybe I'm having a blind spot, but, without having a
> custom metaclass (redefining __getattribute__ differently from the
> implementation in object), how would you do it? I.e. how would you
> code a type instanceproperty such that:
>
>
> class UIP(object):
>
> def getfullname(self): return 'Monty Python'
>
> def __init__(self):
> self.fulname = instanceproperty(self.getfullname)
>
> x = UIP()
> print x.fullname
>
>
> would result in x.getfullname() being _called_? I just can't
> see how, and I'd like to learn -- thanks!
Hmm. It's harder than I thought :)
I naïvely assumed that descriptors worked equally well for instances
as for classes, which turns out not to be true. If it was, it would indeed
be fairly easy...
So I was wrong -- you'd have to define custom metaclass, or something along
those lines. You could probably avoid a metaclass with something like:
class C:
def __init__(self, ...):
instanceproperty(self, 'fullname', self.getfullname)
where instanceproperty was a function that inserted some sort of evil
descriptor into C.fullname if there wasn't already one... but it'd be worse
than simply defining __getattribute__ or __getattr__.
Hmm... maybe you could abuse metaclasses to return a freshly minted class
object instead of a mere instance, so that descriptors would work....
[experiments]
Ok, you could do it like this:
>>> class instanceIsClass(object):
... def __new__(cls):
... class Instance(cls): pass
... return Instance
...
>>>
>>> class C(instanceIsClass):
... def __new__(self):
... self.fullname = property(self.getfullname)
... return object.__new__(self)
...
... def getfullname(self):
... return 'Andrew Bennetts'
...
>>> c = C()
>>> c.fullname
'Andrew Bennetts'
Which isn't too far removed from:
class C:
def __init__(self):
self.fullname = property(self.getfullname)
def getfullname(self):
return 'Andrew Bennetts'
Well, you'd have to stand a few metres back from the monitor and squint, but
then it kinda sorta looks similar <wink>. Perhaps with a bit more
cleverness you could simplify my hack more.
Thanks for helping me realise that I'd assumed wrongly :)
-Andrew.
More information about the Python-list
mailing list