Style question - defining immutable class data members

Aaron Brady castironpi at gmail.com
Mon Mar 16 00:26:04 CET 2009


On Mar 15, 1:50 pm, "Rhodri James" <rho... at wildebst.demon.co.uk>
wrote:
> On Sun, 15 Mar 2009 17:55:25 -0000, Aaron Brady <castiro... at gmail.com>  
> wrote:
>
> > On Mar 15, 12:39 pm, John Posner <jjpos... at snet.net> wrote:
> >> (My apologies if the thread has already covered this.) I believe I  
> >> understand the WHAT in this situation, but I don't understand the WHY  
> >> ...
>
> [snip]
>
>
>
> >> My question is ... WHY does the interpreter silently create the  
> >> instance attribute at this point, causing a "surprising decoupling"  
> >> from the class attribute? WHY doesn't the interpreter behave as it  
> >> would with a simple, non-instance variable:
>
> >>   > python
> >>   Python 2.6.1 ...
> >>   Type "help", "copyright", "credits" or "license" for more information.
>
> >>   >>> x += 1
> >>   Traceback (most recent call last):
> >>     File "<stdin>", line 1, in <module>
> >>   NameError: name 'x' is not defined
>
> >> Is there a beneficial effect of silently creating the instance  
> >> attribute, which outweighs the detrimental effects: (1) inconsistency,  
> >> (2) the "surprising" decoupling?
>
> > Yes.  If you access an attribute, you want the search to go like this:
>
> > - check instance for attribute
> > - check class for attribute
> > - check base classes for attribute
>
> But do you, though?  The only occasion I can think of that I'd want
> the search to go past the instance is this "auto-initialisation",
> and frankly I'd rather do that in an __init__ anyway.  Perhaps
> static methods or class methods work that way, I don't know how
> the innards of the interpreter handle that.

As Bruno stated, yes, for resolving 'self.method', and other
descriptors.  You acknowledge that 'foo.jam' would need to identify
itself as coming from an instance, class, or base, since the only
entries in 'foo's dictionary are those attributes which are particular
to 'foo'.  Others, such as the entries in 'foo's class, are stored in
a different dictionary.  Changes to that class's dictionary are
visible to all 'foo' instances (as desired), as well that as 'foo'
isn't clogged by copies of entries for all of its class's functions.

Class attributes are grouped together in the class dictionary,
instance attributes are grouped together in the instance dictionary,
and instances need to see both.

If you have a counter-proposal, either for a wishlist for behavior, or
a way of arranging its implementation, I for one would entertain it,
even on the c-l-python newsgroup, and even though it wouldn't have
much of a chance of making it in to Python.

As a side note, this argument of 'whose methods am I seeing?' has an
inconvenient artifact: the behavior of 'foo.method'.  'foo.method'
needs to refer to an instance method, due to not needing the 'self'
attribute respecified; while 'foo.__class__.method' needs to refer to
a plain function.  Python's solution is a skeleton type, that just
redirects 'foo.method( )' to an append of the arguments plus call.

> Is there any actual advantage to self.attribute picking up
> Class.attribute instead of raising a NameError?
>
> > If you write an attribute, you want it stored in the attribute, not
>
>                                                         ^^^^^^^^^
>
> > the class or base classes.
>
> I think you meant "instance" there :-)

Syntax error line 4!  Gasp!  All hands to battle stations.

> Actually what I want is for
> the attribute to be stored where I told it, which could well be in
> the class.  If the attribute is specified as "self.attribute", then
> yes, put it in the instance.

The way C++ works is by allocating storage for the data and method
pointers in a class.

class X {
    int foo;
    char jam[ 12 ];
    int foojam( int y, int z ) { ...; }
};

X requires 20 bytes: 4 for 'foo', 12 for 'jam', and 4 for 'foojam'...
under a 32-bit target.  (The 4 for 'foojam' come from a virtual
function table, for polymorphic objects.... er, technically.)

Python can't and won't do that, because you want attributes to be able
to join instances over time.

You get what you want: attributes are stored where you tell them.  But
where are they read from?

>
> --
> Rhodri James *-* Wildebeeste Herder to the Masses




More information about the Python-list mailing list