Style question - defining immutable class data members

Rhodri James rhodri at wildebst.demon.co.uk
Mon Mar 16 03:54:41 CET 2009


On Sun, 15 Mar 2009 23:26:04 -0000, Aaron Brady <castironpi at gmail.com>  
wrote:

> 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]
>> > 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'.

No, I don't acknowledge that.  (Note that John's original question
was *WHY*, and you effectively gave him a *HOW* answer by asserting
that it's what he wants.  I'm playing Devil's Advocate to an extent.)

"self.method" is not the same object as "Class.method"; one's bound
and the other isn't, for starters.  It's therefore by no means
obvious that method lookup isn't being done via the instance's
dictionary.  After all, some kind of binding has to be done at
instance creation time.  If you're telling me that it's time-
efficient (or at least space-efficient and not horribly time-
inefficient) to use the class dictionary and magically know to
wrapper the call, then we've that makes things different and
gives us a reason for wanting that search order.

It's the same story with descriptors; in fact they mask rather
more of the detail of what they're doing and look at first glance
more tightly bound to the instance than the class.  Further steps
get you to the same "why" answer, but they are further steps.

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

True, but they don't need to see both with instance attribute
syntax.  That they can is what we're trying to justify here.

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

Nope, no proposal.  Mildly considering one, but I thought I'd try
understanding why what happens is considered a good thing before I
let my hare-brainedness off the leash.

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

As I said, this inconvenient artefact is exactly why I didn't think
assuming instance method lookup happened via the *class* dictionary
was safe!

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

I'm sorry, I'm utterly baffled.  Why is this relevant to my bit
of pedantry?

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

No, *why*.  These questions aren't about what the search order
is, they're about why there is a search order.

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



More information about the Python-list mailing list