Handling Property and internal ('__') attribute inheritance and creation

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Tue Aug 19 15:06:28 EDT 2008


Rafe a écrit :
> On Aug 16, 1:22 am, Bruno Desthuilliers
> <bdesth.quelquech... at free.quelquepart.fr> wrote:
>> Rafea écrit :
>>
>>> Hi,
>>> I've been thinking in circles about these aspects of Pythonic design
>>> and I'm curious what everyone else is doing and thinks. There are 3
>>> issues here:
>>> 1) 'Declaring' attributes
>> There's nothing like "declaration" of variables/attributes/whatever in
>> Python.
>>
>>> - I always felt it was good code practice to
>>> declare attributes in a section of the class namespace. I set anything
>>> that is constant but anything variable is set again  in __init__():
>>> Class A(object):
>>>     name = "a name"
>>>     type = "a typee"
>>>     childobject = None
>>>     def __init__(self, obj):
>>>         self.childobject = object
>>> This makes it easy to remember and figure out what is in the class.
>>> Granted there is nothing to enforce this, but that is why I called it
>>> 'code practice'. Do you agree or is this just extra work?
>> It's not only extra work, it's mostly a WTF. You create class attributes
>> for no other reasons than to mimic some other mainstream languages. If I
>> was to maintain such code, I'd loose valuable time wondering where these
>> class attributes are used.
>>
>>
>>
>>> 2) Internal attributes (starting with 2x'_') aren't inherited.
>> Yes they are. But you need to manually mangle them when trying to access
>> them from a child class method. FWIW, that *is* the point of
>> __name_mangling  : making sure these attributes won't be accidentally
>> overwritten in a child class.
>>
>>> Do you
>>> just switch to a single '_' when you want an "internal" attribute
>>> inherited? These are attributes I want the classes to use but not the
>>> user of these classes. Of course, like anything else in Python, these
>>> aren't really private. It is just a convention, right? (The example
>>> for #3 shows this.)
>> Yes. The (*very* strong) convention is that
>> _names_with_simple_leading_underscore denote implementation attributes.
>>
>>
>>
>>> 3) It isn't possible to override a piece of a Property Descriptor. To
>>> get around this, I define the necessary functions in the class but I
>>> define the descriptor in the __new__() method so the inherting class
>>> can override the methods. Am I overlooking some basic design principle
>>> here? This seems like a lot of work for a simple behavior. Example:
>>> class Base(object):
>>>     def __new__(cls):
>>>         setattr(cls,
>>>                 "state",
>>>                 property(fget = cls._Get_state,
>>>                          fset = cls._Set_state,
>>>                          fdel = None,
>>>                          doc  = cls._doc_state))
>>>         obj = super(Base, cls).__new__(cls)
>>>         return obj
>>>     state = None    # Set in __new__()
>>>     _state = True
>>>     _doc_state = "The state of this object"
>>>     def _Get_state(self): return self._state
>>>     def _Set_state(self, value): self._state = value
>> pep08 : attribute names (including methods) should be all_lower.
>>
>>> class Child(Base):
>>>     def _Get_state(self):
>>>         # Do some work before getting the state.
>>>         print "Getting the state using the child's method"
>>>         return self._state
>>> print Child().state
>> How often do you really need to override a property ? (hint : as far as
>> I'm concerned, it never happened so far). Now you have two solutions :
>> either redefine the whole property in the derived class, or, if you
>> really intend your property to be overriden, provide a "template method"
>> hook.
>>
>> I'd say you're making things much more complicated than they need to be.
> 
> 
> Thanks Bruno, and everyone ! These are exactly the type of hard
> answers I was hoping for. I'm mostly converted but my brain still
> needs a Pythonic push from time to time. Looks like have some some
> clean up to perform...with confidence.
> 
> I'm interested to see the implementation of getter, etc overrides in
> 2.6/3.0. I have two classes that could be simplified with this. For
> example, I have a class which does a lot of work and has about 5 key
> properties. I want to inherit it, and just trigger an event (update
> something only stored in the child) after 4 of these attributes are
> finished being set. I was thinking about using a callback which is
> empty in the parent

IOW : a template method. Probably one of the most known, most evident 
and most useful design pattern. But...

> or __setattr__() (but I hat using this unless I
> have to, it is still troublesome to me).


Don't use __setattr__ if you can avoid it. It *is* troublesome - and 
costly too.

Now, remember that the property class is just an handy shortcut for the 
most common use of computed attributes. The more generic mechanism 
properties are built upon - the descriptor protocol - is nothing 
complicated, so when you hit the limits of properties (or when 
property-based code becomes too tangled/messy/whatever), you can write 
your own custom descriptor objects.



More information about the Python-list mailing list