From: Ethan Furman on
Bruno Desthuilliers wrote:
> Ethan Furman a �crit :
>> Bruno Desthuilliers wrote:
>>> Bruno Desthuilliers a �crit :
>>>> Ethan Furman a �crit :
>>>>> Bruno Desthuilliers wrote:
>>>>>> Duncan Booth a �crit :
>>>> (snip)
>>>>
>>>>>>> Or you could create the default as a class attribute
>>>>>>
>>>>>> from the OP:
>>>>>> """
>>>>>> 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 this solution won't obviously work in this case !-)
>>>>>>
>>>>>> Also and FWIW, I wouldn't advocate this solution if the "default"
>>>>>> class attribute is of a mutable type.
>>>>>
>>>>> Well, it is Monday, so I may be missing something obvious, but what
>>>>> is the effective difference between these two solutions?
>>>>
>>>
>>> If you meant "what is the difference between creating the "whatever"
>>> attribute with a default value in the initializer and creating it on
>>> demand in the __getattr__ hook", the main difference is that in the
>>> first case, the instance is garanteed to have this attribute, so you
>>> get rid of "hasattr" checks (and the unwanted side effects) or,
>>> worse, direct check of the instance __dict__. Except for a couple of
>>> corner case, client code shouldn't have to worry about this kind of
>>> things - this breaks encapsulation.
>>
>> Yay Tuesday! :D
>>
>> What I meant was what is the difference between:
>>
>> [Bruno Desthuilliers]
>> > DEFAULT_WHATEVER = Whathever()
>> > class MyClass(object):
>> > def __init__(self, x, y):
>> > self.size = DEFAULT_WHATEVER
>>
>> and
>>
>> [Duncan Booth]
>> > class MyClass(object):
>> > size = Whatever()
>> > def __init__(self, x, y):
>> > ...
>>
>> in both cases the object ends up with a size attribute and no further
>> need of __getattr__. Of course, the warning about having a mutable
>> object as a class attribute stands.
>
> Indeed.
>
>> To phrase it another way, why does your solution (Bruno) work, but
>> Duncan's "obviously won't"?
>
> As it is written (and assuming the name "Whatever" is bound to a
> callable !-)), Duncan's code would work, even if it might not be the
> safest solution in the case of a mutable type.
>
> The problem here is that the OP stated that the "size" attribute was to
> be of the same type as the host class, so the code would look something
> like:
>
> class MyClass(object):
> size = MyClass()
>
> which will raise a NameError, since MyClass is not yet defined when
> "size=MyClass()" is executed.

Ah ha! I *knew* I was missing something. Thank you for the
explanation. So the correct methods, then, would be to either include
the size attribute in the __init__, or add it to the class /after/ the
class was defined.

I feel much better now... slightly silly, but better. ;)

~Ethan~