Python dynamic attribute creation

Alexander Kapps alex.kapps at web.de
Mon Jun 28 15:09:33 EDT 2010


Bruno Desthuilliers wrote:
> Alexander Kapps a écrit :
> (snip)
>> While I personally don't agree with this proposal (but I understand 
>> why some people might want it), I can see a reason.
>>
>> When disallowing direct attribute creation, those typos that seem to 
>> catch newcommers won't happen anymore. What I mean is this:
>>
>> class Foo(object):
>>     def __init__(self):
>>         self.somearg = 0
>>
>> f = Foo()
>> f.soemarg = 42
>>
>> ---^ There, typo, but still working
>>
>> It's something like a custom __setattr__ that errors out when trying 
>> to assign to an attribute that doesn't exists,
> 
> Chicken and egg problem, really :  f.__dict__['somearg'] doesn't exists 
> until "self.somearg = 0" is executed.
> 
> The "problem" is that Python's methods are only thin wrapper around 
> functions (cf http://wiki.python.org/moin/FromFunctionToMethod) so 
> there's no difference between "self.somearg = 0" in Foo.__init__ and 
> "f.somearg = 42".
> 
> IOW, there's no way to implement this proposal without completely 
> changing Python's object model.

I must be missing something. Can you please explain why the whole 
object model would need to change?

This seems to work quite well:

class TypoProtection(object):
     def __init__(self):
         self.foo = 42
         self.bar = 24

         def _setattr(self, name, value):
             if name in self.__dict__:
                 self.__dict__[name] = value
             else:
                 raise AttributeError, "%s has no '%s' attribute" \
                                       % (self.__class__, name)


         self.__class__.__setattr__ = _setattr


t = TypoProtection()

t.foo = "spam"
t.bar = "ham"
t.parrot = "dead"



Traceback (most recent call last):
   File "typo.py", line 20, in <module>
     t.parrot = "dead"
   File "typo.py", line 10, in _setattr
     raise AttributeError, "%s has no '%s' attribute" % 
(self.__class__, name
AttributeError: <class '__main__.TypoProtection'> has no 'parrot' 
attribute


So, IIUC, all what would need to be done is to add an implicit 
__setattr__ at the end of __init__ .

(Just want to understand, still not advocating this proposal)




More information about the Python-list mailing list