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

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Fri Aug 15 14:22:23 EDT 2008


Rafe a é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.




More information about the Python-list mailing list