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

Rafe rafesacks at gmail.com
Tue Aug 19 16:36:35 CEST 2008


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 or __setattr__() (but I hat using this unless I
have to, it is still troublesome to me).

- Rafe





More information about the Python-list mailing list