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

R

Rafe

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 - 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?


2) Internal attributes (starting with 2x'_') aren't inherited. 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.)


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

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



Please share your thoughts,

- Rafe
 
B

Bruno Desthuilliers

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.
 
C

Christian Heimes

Bruno said:
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.

In Python 2.6 and 3.0 you can override the setter, getter or deleter of
a property in a subclass. You may be able to find a pure Python
implementation written by Guido. My C implementation in the core works
almost the same.

Christian
 
E

Eric Brunel

1) 'Declaring' attributes - 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?

To add to what others have already said, it is not only 'just extra work',
it is also quite dangerous. See:

class A(object):
children = []

Now *all* A instances share the *same* list, as it was defined as a class
attribute. If you ever forget to set it to something else in __init__,
you're in for big surprises.

What I'm doing is set all instance attributes right at the beginning of
the __init__ with a huge comment before them, like:

class A(object):
def __init__(self):
## INSTANCE ATTRIBUTES:
## --------------------
self.children = []

This way, you still can 'figure out what is in the class' quite quickly,
without the drawbacks of declaraing class attributes.

HTH
 
F

Fredrik Lundh

Eric said:
To add to what others have already said, it is not only 'just extra
work', it is also quite dangerous. See:

class A(object):
children = []

the OP is aware of that, of course:
> I set anything that is constant but anything variable is set again in
> __init__()

as long as if you're aware of the issues involved (which you should be
if you're using Python professionally), using class-level attributes is
a perfectly valid Python style.

</F>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top