hasattr + __getattr__: I think this is Python bug

Jean-Michel Pichavant jeanmichel at sequans.com
Tue Jul 20 11:52:25 EDT 2010


dmitrey wrote:
> On 20 июл, 15:00, Jean-Michel Pichavant <jeanmic... at sequans.com>
> wrote:
>   
>> dmitrey wrote:
>>     
>>> hi all,
>>> I have a class (FuncDesigner oofun) that has no attribute "size", but
>>> it is overloaded in __getattr__, so if someone invokes
>>> "myObject.size", it is generated (as another oofun) and connected to
>>> myObject as attribute.
>>>       
>>> So, when I invoke in other code part "hasattr(myObject, 'size')",
>>> instead o returning True/False it goes to __getattr__ and starts
>>> constructor for another one oofun, that wasn't intended behaviour.
>>> Thus "hasattr(myObject, 'size')" always returns True. It prevents me
>>> of some bonuses and new features to be done in FuncDesigner.
>>>       
>>>>>> 'size' in dir(b)
>>>>>>             
>>> False
>>>       
>>>>>> hasattr(b,'size')
>>>>>>             
>>> True
>>>       
>>>>>> 'size' in dir(b)
>>>>>>             
>>> True
>>>       
>>> Could you fix it?
>>>       
>> Quite simple, when calling b.size, return the computed value but do not
>> set it as attribute, the value will be computed on each b.size call, and
>> hasattr w. If you don't want to compute it each time, cause there no
>> reason for it to change, use a private dummy attribute to record the
>> value instead of size (__size for instance) and return the value of
>> __size when getting the value of size.
>>
>> class Foo(object):
>>     def __init__(self):
>>         self.__size = None
>>
>>     def __getattr__(self, name):
>>         if name == "size":
>>             if self.__size is None:
>>                 self.__size = 5 # compute the value
>>             return self.__size
>>         raise AttributeError(name)
>>
>> b = Foo()
>> print 'size' in dir(b)
>> print hasattr(b, 'size')
>> print 'size' in dir(b)
>>
>> False
>> True
>> False
>>
>> JM
>>     
>
> This doesn't stack with the following issue: sometimes user can write
> in code "myObject.size = (some integer value)" and then it will be
> involved in future calculations as ordinary fixed value; if user
> doesn't supply it, but myObject.size is involved in calculations, then
> the oofun is created to behave like similar numpy.array attribute.
>   
Here are some solutions in my humble order of preference:
1/ ask the user to always fill the size field
2/ ask the user to never fill the size filed (you can override 
__setattr__ to make sure...)
3/ override __setattr__ to set __size instead of size

JM



More information about the Python-list mailing list