__getattr__, __setattr__ and pickle

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Wed Aug 13 08:34:15 EDT 2008


mwojc a écrit :
> Bruno Desthuilliers wrote:
> 
>>  >>> class Prop(object):
>> ...     @apply
>> ...     def prop():
>> ...         def fget(self): return self._prop
>> ...         def fset(self, val): self._prop = val
>> ...         return property(**locals())
>> ...     def __init__(self, val): self.prop=val
>> ...
>>  >>> class Hook(object):
>> ...     def __getattr__(self, name):
>> ...         if name == 'prop':
>> ...             return self._prop
>> ...         raise AttributeError("yadda")
>> ...     def __setattr__(self, name, val):
>> ...         if name ==  'prop':
>> ...             self.__dict__['_prop'] = val
>> ...         else:
>> ...             # XXX : INCORRECT IMPLEMENTATION, DONT DO THIS !
>> ...             self.__dict__[name] = val
>> ...             # correct implementation:
>> ...             # super(Hook, self).__setattr__(name, value)
>> ...     def __init__(self, val): self.prop=val
> 
> Hi!
> Finally i ended up with all the suggestions you gave me. The speed is
> important to me besause i get/set my attribute a lot... The only doubts i
> have are with the @apply decorator, because 'apply' seems to be depreciated
> since python 2.3...

As far as I can tell, it should stay until Python 3.0. But you don't 
have to write your properties that way anyway - it's just something I 
personnaly find to be a convenient shortcut, period. FWIW, the above 
code is just a copy/paste from an interactive session, not an example of 
"clean" Python coding.

> And another thing: why writing for all
> attributes 'self.__dict__[name] = val' in __setattr__ is incorrect?

Because __setattr__ is *always* called. With your above solution, 
read/write properties setters won't be called.

Python 2.5.1 (r251:54863, Mar  7 2008, 03:41:45)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
 >>> class Foo(object):
     @apply
     def bar():
         def fget(self):
             print "bar get"
             return self._bar
         def fset(self, val):
             print "bar set"
             self._bar = val
     def __getattr__(self, name):
         print "__getattr__", name
         if name == 'baaz':
             return self._baaz
         raise AttributeError("yadda")
     def __setattr__(self, name, val):
         print "__setattr__", name
         self.__dict__[name] = val
 >>> foo = Foo('bar', 'baaz')
__setattr__ bar
__setattr__ baaz
 >>> foo.baaz
'baaz'
 >>> foo.bar
'bar'
 >>> foo.__dict__
{'baaz': 'baaz', 'bar': 'bar'}




More information about the Python-list mailing list