Handling Property and internal ('__') attribute inheritance and creation
bdesth.quelquechose at free.quelquepart.fr
Tue Aug 19 21:06:28 CEST 2008
Rafe a écrit :
> On Aug 16, 1:22 am, Bruno Desthuilliers
> <bdesth.quelquech... at free.quelquepart.fr> wrote:
>> Rafea écrit :
>>> 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
>>> - 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):
>>> 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"
>> 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
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