Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Style question - defining immutable class data members

1 view
Skip to first unread message

Maxim Khitrov

unread,
Mar 14, 2009, 12:32:56 PM3/14/09
to pytho...@python.org
Very simple question on the preferred coding style. I frequently write
classes that have some data members initialized to immutable values.
For example:

class Test(object):
def __init__(self):
self.some_value = 0
self.another_value = None

Similar effect can be achieved by defining some_value and
another_value for the entire class, like so:

class Test(object):
some_value = 0
another_value = None

The advantage of doing this is that the assignments are evaluated once
and thus the creation of that class is a bit faster. Access is still
performed through self.some_value and self.another_value. Is there a
reason to prefer the first style over the second?

- Max

MRAB

unread,
Mar 14, 2009, 12:50:59 PM3/14/09
to pytho...@python.org
In the first case each instance has its own attributes, whereas in the
second case the attributes belong to the class and are thus shared by
all the instances. Which you use depends on whether you want them shared
or not.

Maxim Khitrov

unread,
Mar 14, 2009, 1:28:25 PM3/14/09
to MRAB, pytho...@python.org

When the types are immutable, there is no difference. The second case
is faster and consumes less memory (initially), but nothing else
changes. I'm simply asking if it is considered poor style to define
data members for the class when they are only used by instances.

- Max

bearoph...@lycos.com

unread,
Mar 14, 2009, 1:57:12 PM3/14/09
to
Maxim Khitrov:

> When the types are immutable, there is no difference.

But you may want different instances to have different immutable data.

Generally if the data (immutable or not) is the same for all the
instances, use class attributes, otherwise use instance attributes.

Bye,
bearophile

Gary Herron

unread,
Mar 14, 2009, 2:07:25 PM3/14/09
to pytho...@python.org
Maxim Khitrov wrote:
> Very simple question on the preferred coding style. I frequently write
> classes that have some data members initialized to immutable values.
> For example:
>
> class Test(object):
> def __init__(self):
> self.some_value = 0
> self.another_value = None
>
> Similar effect can be achieved by defining some_value and
> another_value for the entire class, like so:
>
> class Test(object):
> some_value = 0
> another_value = None
>
> The advantage of doing this is that the assignments are evaluated once
> and thus the creation of that class is a bit faster. Access is still
> performed through self.some_value and self.another_value. Is there a
> reason to prefer the first style over the second?
>
> - Max
> --
> http://mail.python.org/mailman/listinfo/python-list
>
Such things are often called class attributes, and the are fine. If you
look through Python's standard library, you will find many examples of
class attributes.

However, you appear to have either a misuse or misconception of the word
"immutable' here. Whether the value you assign to a class attribute is
mutable or immutable is irrelevant. Also whether you plan on leaving
the value constant or not is also not relevant.

What does matter is this: If every instance wants access to a single
value (immutable or not), use a class attribute, otherwise use an
instance attribute.

Gary Herron

Terry Reedy

unread,
Mar 14, 2009, 2:26:40 PM3/14/09
to pytho...@python.org
Maxim Khitrov wrote:
> On Sat, Mar 14, 2009 at 12:50 PM, MRAB <goo...@mrabarnett.plus.com> wrote:
>> Maxim Khitrov wrote:
>>> Very simple question on the preferred coding style. I frequently write
>>> classes that have some data members initialized to immutable values.
>>> For example:
>>>
>>> class Test(object):
>>> def __init__(self):
>>> self.some_value = 0
>>> self.another_value = None
>>>
>>> Similar effect can be achieved by defining some_value and
>>> another_value for the entire class, like so:
>>>
>>> class Test(object):
>>> some_value = 0
>>> another_value = None
>>>
>>> The advantage of doing this is that the assignments are evaluated once
>>> and thus the creation of that class is a bit faster. Access is still
>>> performed through self.some_value and self.another_value. Is there a
>>> reason to prefer the first style over the second?
>>>
>> In the first case each instance has its own attributes, whereas in the
>> second case the attributes belong to the class and are thus shared by
>> all the instances. Which you use depends on whether you want them shared
>> or not.
>
> When the types are immutable, there is no difference. The second case
> is faster and consumes less memory (initially), but nothing else
> changes. I'm simply asking if it is considered poor style to define
> data members for the class when they are only used by instances.

If they are class constants (the same for all instances, I would define
them as such. If duplicated for all instances in __init__, I would
expect there to be methods that replace them. I particular, I would
expect that .some_value would possibly get a value other than 0.

Maxim Khitrov

unread,
Mar 14, 2009, 3:01:14 PM3/14/09
to Gary Herron, pytho...@python.org
On Sat, Mar 14, 2009 at 2:07 PM, Gary Herron <ghe...@islandtraining.com> wrote:
> Maxim Khitrov wrote:
>>
>> Very simple question on the preferred coding style. I frequently write
>> classes that have some data members initialized to immutable values.
>> For example:
>>
>> class Test(object):
>>    def __init__(self):
>>        self.some_value = 0
>>        self.another_value = None
>>
>> Similar effect can be achieved by defining some_value and
>> another_value for the entire class, like so:
>>
>> class Test(object):
>>    some_value = 0
>>    another_value = None
>>
>> The advantage of doing this is that the assignments are evaluated once
>> and thus the creation of that class is a bit faster. Access is still
>> performed through self.some_value and self.another_value. Is there a
>> reason to prefer the first style over the second?
>>
>> - Max
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> Such things are often called class attributes, and the are fine.  If you
> look through Python's standard library,  you will find many examples of
> class attributes.
>
> However, you appear to have either a misuse or misconception of the word
> "immutable' here.   Whether the value you assign to a class attribute is
> mutable or immutable is irrelevant.   Also whether you plan on leaving the
> value constant or not is also not relevant.
> What does matter is this:  If every instance wants access to a single value
> (immutable or not), use a class attribute, otherwise use an instance
> attribute.
>
> Gary Herron

Perhaps a different example would help explain what I'm trying to do:

class Case1(object):
def __init__(self):
self.count = 0
self.list = []

def inc(self):
self.count += 1
self.list.append(self.count)

def val(self):
return (self.count, self.list)

class Case2(object):
count = 0
list = []

def inc(self):
self.count += 1
self.list.append(self.count)

def val(self):
return (self.count, self.list)

for i in xrange(10):
c1 = Case1()
c2 = Case2()

for j in xrange(i):
c1.inc()
c2.inc()

v1, l1 = c1.val()
v2, l2 = c2.val()

print v1 == v2, l1 == l2

The only difference between Case1 and Case2 classes is where the count
and list attributes are defined. You will notice that for an immutable
type (count), this doesn't matter. On the last line, v1 == v2 is
always True. When the type is mutable (list), you must define it in
__init__. This isn't about class attributes or shared instance
attributes/constants. This is about a small optimization in defining
per-instance variables. This optimization only applies to immutable
types.

- Max

David Stanek

unread,
Mar 14, 2009, 3:25:37 PM3/14/09
to Maxim Khitrov, pytho...@python.org
On Sat, Mar 14, 2009 at 12:32 PM, Maxim Khitrov <mkhi...@gmail.com> wrote:
> Very simple question on the preferred coding style. I frequently write
> classes that have some data members initialized to immutable values.
> For example:
>
> class Test(object):
>    def __init__(self):
>        self.some_value = 0
>        self.another_value = None
>
> Similar effect can be achieved by defining some_value and
> another_value for the entire class, like so:
>
> class Test(object):
>    some_value = 0
>    another_value = None
>
> The advantage of doing this is that the assignments are evaluated once
> and thus the creation of that class is a bit faster. Access is still
> performed through self.some_value and self.another_value. Is there a
> reason to prefer the first style over the second?
>

In general I think it can be fine as long as you do use immutable
values. I use this pattern when I create data transfer objects[0].
Normally these objects don't have any methods. So you want to be
careful that you are doing it for the right reason. When I create
objects that are not DTOs I don't do this.

[0] http://martinfowler.com/eaaCatalog/dataTransferObject.html

--
David
blog: http://www.traceback.org
twitter: http://twitter.com/dstanek

Gary Herron

unread,
Mar 14, 2009, 4:31:29 PM3/14/09
to pytho...@python.org
Maxim Khitrov wrote:
> On Sat, Mar 14, 2009 at 2:07 PM, Gary Herron <ghe...@islandtraining.com> wrote:
>
>> Maxim Khitrov wrote:
>>
>>> Very simple question on the preferred coding style. I frequently write
>>> classes that have some data members initialized to immutable values.
>>> For example:
>>>
>>> class Test(object):
>>> def __init__(self):
>>> self.some_value = 0
>>> self.another_value = None
>>>
>>> Similar effect can be achieved by defining some_value and
>>> another_value for the entire class, like so:
>>>
>>> class Test(object):
>>> some_value = 0
>>> another_value = None
>>>
>>> The advantage of doing this is that the assignments are evaluated once
>>> and thus the creation of that class is a bit faster. Access is still
>>> performed through self.some_value and self.another_value. Is there a
>>> reason to prefer the first style over the second?
>>>
> --
> http://mail.python.org/mailman/listinfo/python-list
>

But now you are not listening to what people are telling you. It has
*nothing* to do with the mutability/immutability of the integer and the
list your two classes create.

The difference is this:

For C1: You create 10 instances of C1. Each one creates its own
count, and a list variables, and manipulates them calls to inc and val.
Then each on is discarded as you go through the next pass on the outer loop.

For C2; You create 10 instances of C2, but these 10 instances each
manipulate values created once in the class itself. The values
manipulated by one instance of C2 in one pass through the loop are not
affected when, on the next pass through the loop, that instance is
destroyed and another instance is created.

So...

If you want a variable that records/supplies some value across *all*
instances of a class, use a class variable.
(Or use a global variable -- it would have the same effect.)

If you want a variable whose value is unique to each instance of a
class, then make it an instance variable.

Gary Herron

Terry Reedy

unread,
Mar 14, 2009, 4:36:50 PM3/14/09
to pytho...@python.org
Maxim Khitrov wrote:

> Perhaps a different example would help explain what I'm trying to do:
>
> class Case1(object):
> def __init__(self):
> self.count = 0
> self.list = []
>
> def inc(self):
> self.count += 1
> self.list.append(self.count)
>
> def val(self):
> return (self.count, self.list)

OK, so .count and .list (BAD IDEA TO USE BUILT-IN NAME) are not
constants, as you previously implied.

>
> class Case2(object):
> count = 0
> list = []
>
> def inc(self):
> self.count += 1
> self.list.append(self.count)
>
> def val(self):
> return (self.count, self.list)
>
> for i in xrange(10):

You really only need one value of i for a test. But you need multiple
instances of each class

> c1 = Case1()
> c2 = Case2()

c1a, c1b = Case1(), Case1()
c2a, c2b = Case2(), Case2()

> for j in xrange(i):
> c1.inc()
> c2.inc()

c1a.inc(), c1b.inc()
c2a.inc(), c2b,inc()


>
> v1, l1 = c1.val()
> v2, l2 = c2.val()

print(c1a.val(), c1b.val(), c2a.val(), c2b.val())


>
> print v1 == v2, l1 == l2

# just look as all four tuples


>
> The only difference between Case1 and Case2 classes is where the count
> and list attributes are defined.

and that 'only difference makes a major difference. Make two instances
of each class and you will see how.

Terry Jan Reedy


Matthew Woodcraft

unread,
Mar 14, 2009, 5:38:18 PM3/14/09
to
Gary Herron <ghe...@islandtraining.com> writes:

> But now you are not listening to what people are telling you. It has
> *nothing* to do with the mutability/immutability of the integer and the list
> your two classes create.

No! Did you run the code he posted? The immutability makes all the
difference.


> The difference is this:

> For C1: You create 10 instances of C1. Each one creates its own
> count, and a list variables, and manipulates them calls to inc and
> val. Then each on is discarded as you go through the next pass on the
> outer loop.

> For C2; You create 10 instances of C2, but these 10 instances each
> manipulate values created once in the class itself. The values
> manipulated by one instance of C2 in one pass through the loop are not
> affected when, on the next pass through the loop, that instance is
> destroyed and another instance is created.

If you try it, you will see that this isn't true for C2, in the case of
the immutable object. That's because given this code:

class Foo(object):
x = 0

def inc(self):
self.x += 1

when inc is called, it creates an 'x' attribute on the instance, even
though one didn't exist before, and it doesn't change the value of the
class attribute.

If 'x' were a list, the new instance attribute would refer to the same
object as the class attribute, so it wouldn't make much difference. But
when the original class attribute was an immutable object, they become
'decoupled'.


I think this code is in poor taste: it's clear that it will confuse
people (which is what Maxim was asking about in the first place).

-M-

Maxim Khitrov

unread,
Mar 14, 2009, 5:43:42 PM3/14/09
to Gary Herron, tjr...@udel.edu, pytho...@python.org
On Sat, Mar 14, 2009 at 4:31 PM, Gary Herron <ghe...@islandtraining.com> wrote:
>> Perhaps a different example would help explain what I'm trying to do:
>>
>> class Case1(object):
>>        def __init__(self):
>>                self.count = 0
>>                self.list  = []
>>
>>        def inc(self):
>>                self.count += 1
>>                self.list.append(self.count)
>>
>>        def val(self):
>>                return (self.count, self.list)
>>
>> class Case2(object):
>>        count = 0
>>        list  = []
>>
>>        def inc(self):
>>                self.count += 1
>>                self.list.append(self.count)
>>
>>        def val(self):
>>                return (self.count, self.list)
>>
>> for i in xrange(10):
>>        c1 = Case1()
>>        c2 = Case2()
>>
>>        for j in xrange(i):
>>                c1.inc()
>>                c2.inc()
>>
>>        v1, l1 = c1.val()
>>        v2, l2 = c2.val()
>>
>>        print v1 == v2, l1 == l2
>>
>> The only difference between Case1 and Case2 classes is where the count
>> and list attributes are defined. You will notice that for an immutable
>> type (count), this doesn't matter. On the last line, v1 == v2 is
>> always True. When the type is mutable (list), you must define it in
>> __init__. This isn't about class attributes or shared instance
>> attributes/constants. This is about a small optimization in defining
>> per-instance variables. This optimization only applies to immutable
>> types.
>>
>> - Max
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> But now you are not listening to what people are telling you.  It has
> *nothing* to do with the mutability/immutability of the integer and the list
> your two classes create.
>
> The difference is this:
>
>   For C1:  You create 10 instances of C1.  Each one creates its own  count,
> and a list variables, and manipulates them calls to inc and val.  Then each
> on is discarded as you go through the next pass on the outer loop.

Correct, though the discarded part makes no difference.

>   For C2;  You create 10 instances of C2, but these 10 instances each
> manipulate values created once in the class itself.  The values manipulated
> by one instance of C2 in one pass through the loop are not affected when, on
> the next pass through the loop, that instance is destroyed and another
> instance is created.

> So...

Incorrect. Only the count is unaffected, which was the whole point of
my question.

>  If you want a variable that records/supplies some value across *all*
> instances of a class, use a class variable.  (Or use a global variable -- it
> would have the same effect.)
>
>  If you want a variable whose value is unique to each instance of a class,
> then make it an instance variable.
>
> Gary Herron

I never thought that such simple question would turn into this. David
Stanek gave me the answer I was looking for (thank you). You, on the
other hand, are still going after the wrong issue. Once again, here's
the same example using Terry's suggestions. No class instances are
being destroyed until the very end.

class Case1(object):
def __init__(self):
self.count = 0
self.list = []

def inc(self):
self.count += 1
self.list.append(self.count)

def val(self):
return (self.count, self.list)

class Case2(object):


count = 0
list = []

def inc(self):
self.count += 1
self.list.append(self.count)

def val(self):
return (self.count, self.list)

c1a, c1b = Case1(), Case1()


c2a, c2b = Case2(), Case2()

c1a.inc(), c1b.inc()
c2a.inc(), c2b.inc()

print c1a.val(), c1b.val(), c2a.val(), c2b.val()

And the output:
(1, [1]), (1, [1]), (1, [1, 1]), (1, [1, 1])

The first element of every tuple is the same. This is the count, which
is immutable. The second element is not the same for c2[a,b]. This is
the list, which is mutable. My question was about immutable values,
and for those the who cases are identical. In the second case, c2a and
c2b begin with count referring to the same '0' object. This is where
the time and space savings are made. But because that object is
immutable, when += 1 operation is performed, a copy is made for each
instance. At that point, I am not sharing any values between class
instances.

The whole point is that this is a quick(er) way of providing initial
values for class instance variables when those values are immutable.
When/if that initial value is changed, a copy is made. In Case1, that
copy is made from the very begging in __init__. Please try to
understand what the question is about before responding to it.

- Max

Maxim Khitrov

unread,
Mar 14, 2009, 5:47:55 PM3/14/09
to Matthew Woodcraft, pytho...@python.org
On Sat, Mar 14, 2009 at 5:38 PM, Matthew Woodcraft
<mat...@woodcraft.me.uk> wrote:

> Gary Herron <ghe...@islandtraining.com> writes:
> I think this code is in poor taste: it's clear that it will confuse
> people (which is what Maxim was asking about in the first place).

Yes, I see that now, thanks :)

- Max

Torsten Bronger

unread,
Mar 14, 2009, 5:49:54 PM3/14/09
to
Hallöchen!

Maxim Khitrov writes:

> [...]


>
> The advantage of doing this is that the assignments are evaluated
> once and thus the creation of that class is a bit faster. Access
> is still performed through self.some_value and
> self.another_value. Is there a reason to prefer the first style
> over the second?

I think that tools like epydoc can generate more accurate API
documentation if you write them as instance attributes.

Tschö,
Torsten.

--
Torsten Bronger, aquisgrana, europa vetus
Jabber ID: torsten...@jabber.rwth-aachen.de

Gary Herron

unread,
Mar 14, 2009, 7:30:00 PM3/14/09
to pytho...@python.org


No, you are still misinterpreting your results. But you can be forgiven
because this is quite a subtle point about Python's attribute access.

Here's how it works:

On access, self.count (or self.anything) attempts to find "count" in the
instance variable "self". If that fails, it attempts to lookup "count"
in the class. If that fails it attempts to lookup "count" in a global
context, ...). However, on assignment self.count=... *must*
necessarily mean the local instance variable -- no defaulting to a class
variable on assignment.

So ...

With your class C2, the line
self.count +=1
which really translates into
self.count = self.count + 1
has two different actions depending on the pass through the inner loop.
The first time through (when no instance variable "count" exists), that
line means
<create and assign instance variable "count"> = <class variable
count> + 1
and succeeding passes through (now that self.count is defined) become
<instance count> = <instance count> +1
which is now the same as your class C1

To complete the subtlety, if you were to do
self.list = self.list + [i]
you would see list behaving just as count. However since,
list.append(...)
is an in-place operation, and not an assignment, the creation of an
instance variable
is not provoked, and so all instances continue using the single class
variable.

There is a lesson to be learned here.

Class variables can't be the target of an assignment through self,
because that
creates an instance variable. You can, however, assign to a class
variable through
the class:
C2.count = ...

Gary Herron

unread,
Mar 14, 2009, 7:34:00 PM3/14/09
to pytho...@python.org
Maxim Khitrov wrote:
> On Sat, Mar 14, 2009 at 5:38 PM, Matthew Woodcraft
> <mat...@woodcraft.me.uk> wrote:
>
>> Gary Herron <ghe...@islandtraining.com> writes:
>> I think this code is in poor taste: it's clear that it will confuse
>> people (which is what Maxim was asking about in the first place).
>>

Careful now -- I didn't write that. (Although I agree that it is
confusing.)

Gary Herron

>
> Yes, I see that now, thanks :)
>

Matthew Woodcraft

unread,
Mar 15, 2009, 9:26:17 AM3/15/09
to
Gary Herron <ghe...@islandtraining.com> writes:

It seems clear to me that Maxim understood all this when he asked his
original question (you need to understand this subtlety to know why
the trick he was asking about only works for immutable values).

I wish people on this mailing list|newsgroup would be a little more
ready to assume that people really are asking the question they wrote,
and not the FAQ that sounds most like it.

-M-

Rhodri James

unread,
Mar 15, 2009, 9:56:14 AM3/15/09
to pytho...@python.org
On Sun, 15 Mar 2009 13:26:17 -0000, Matthew Woodcraft
<mat...@woodcraft.me.uk> wrote:

[snip Gary Herron's explanation of instance attribute lookup
falling back to class attribute lookup]

> It seems clear to me that Maxim understood all this when he asked his
> original question (you need to understand this subtlety to know why
> the trick he was asking about only works for immutable values).

It seems equally clear to me that Maxim didn't understand any of this
when he asked his original question, since he appeared to view class
attributes purely as initialisers.

Given that either of us could be right, Gary's assumption of less
understanding rather than more is clearly the safer one to take.

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

Matthew Woodcraft

unread,
Mar 15, 2009, 11:05:04 AM3/15/09
to
"Rhodri James" <rho...@wildebst.demon.co.uk> writes:

> On Sun, 15 Mar 2009 13:26:17 -0000, Matthew Woodcraft

>> It seems clear to me that Maxim understood all this when he asked his


>> original question (you need to understand this subtlety to know why
>> the trick he was asking about only works for immutable values).
>
> It seems equally clear to me that Maxim didn't understand any of this
> when he asked his original question, since he appeared to view class
> attributes purely as initialisers.

Not at all.

He said: << Look, here's a tricky way to use a class attribute as an
initialiser. Is this good style? >>.

What was there in his post that makes you think he viewed class
attributes purely as initialisers?


> Given that either of us could be right, Gary's assumption of less
> understanding rather than more is clearly the safer one to take.

As a general rule, making that assumption runs the risk of being rude or
patronising, so the respondent should be very careful how to phrase the
response. c.l.py is friendlier than many newsgroups, but it could still
do much better.


But in this particular case, statements like


> However, you appear to have either a misuse or misconception of the
> word "immutable' here. Whether the value you assign to a class
> attribute is mutable or immutable is irrelevant.

are wrong as well as unhelpfully phrased.

-M-

Rhodri James

unread,
Mar 15, 2009, 12:25:15 PM3/15/09
to Matthew Woodcraft, pytho...@python.org
On Sun, 15 Mar 2009 15:05:04 -0000, Matthew Woodcraft
<mat...@woodcraft.me.uk> wrote:

> "Rhodri James" <rho...@wildebst.demon.co.uk> writes:
>
>> On Sun, 15 Mar 2009 13:26:17 -0000, Matthew Woodcraft
>
>>> It seems clear to me that Maxim understood all this when he asked his
>>> original question (you need to understand this subtlety to know why
>>> the trick he was asking about only works for immutable values).
>>
>> It seems equally clear to me that Maxim didn't understand any of this
>> when he asked his original question, since he appeared to view class
>> attributes purely as initialisers.
>
> Not at all.
>
> He said: << Look, here's a tricky way to use a class attribute as an
> initialiser. Is this good style? >>.
>
> What was there in his post that makes you think he viewed class
> attributes purely as initialisers?

My lack of sleep :-(

Bruno Desthuilliers

unread,
Mar 15, 2009, 11:30:21 AM3/15/09
to
Maxim Khitrov a écrit :

This above statement does 3 things:

1/ read "self.count", which, *the first time this method is called*,
resolves to self.__class__.count since by that time, there's no instance
attribute named 'count'

2/ add one to the int object returned by looking up 'self.count'

3/ store the result as instance attribute named 'count'.

IOW, the first calls to the method reads the class 'count' attribute and
creates the instance 'count' attribute. Subsequent calls will resolve
'self.count' as the instance attribute since it now exists.


> self.list.append(self.count)

And this statement:

1/ read 'self.list', which resolves to self.__class__.list (the class
attribute) since there's no instance attribute named 'list'

2/ mutate the class attribute

>
> The only difference between Case1 and Case2 classes is where the count
> and list attributes are defined. You will notice that for an immutable
> type (count), this doesn't matter.

cf above.

> On the last line, v1 == v2 is
> always True. When the type is mutable (list), you must define it in
> __init__.

Try rebinding self.list instead of mutating it, and you'll find out that
it's not related to immutable/mutable types, but to how Python's object
model works wrt/ attribute lookup and attribute binding.

An simple example being worth a thousand words:

class Case3(object):


count = 0
list = []

def inc(self):
print self.__dict__
self.count += 1
self.list = self.list + [self.count]
print self.__dict__

def val(self):
return (self.count, self.list)

>>> c = Case3()
>>> print c.__dict__
{}
>>> print c.__class__.__dict__
{'count': 0, '__module__': '__main__', 'val': <function val at
0xb7c7bd4c>, 'list': [], '__dict__': <attribute '__dict__' of 'Case3'
objects>, '__weakref__': <attribute '__weakref__' of 'Case3' objects>,
'__doc__': None, 'inc': <function inc at 0xb7c81844>}
>>> c.inc()
{}
{'count': 1, 'list': [1]}
>>> print c.__dict__
{'count': 1, 'list': [1]}
>>> print c.__class__.__dict__
{'count': 0, '__module__': '__main__', 'val': <function val at
0xb7c7bd4c>, 'list': [], '__dict__': <attribute '__dict__' of 'Case3'
objects>, '__weakref__': <attribute '__weakref__' of 'Case3' objects>,
'__doc__': None, 'inc': <function inc at 0xb7c81844>}
>>>


> This isn't about class attributes or shared instance
> attributes/constants.

Yes, it is.

> This is about a small optimization in defining
> per-instance variables. This optimization only applies to immutable
> types.

Wrong conclusions, sorry.

HTH

Aaron Brady

unread,
Mar 15, 2009, 1:02:03 PM3/15/09
to
On Mar 15, 8:56 am, "Rhodri James" <rho...@wildebst.demon.co.uk>
wrote:

> On Sun, 15 Mar 2009 13:26:17 -0000, Matthew Woodcraft  
>

It's interesting Rhodri chose the safety dimension as the deciding
factor: Gary's assumption might have other faults, but it's safer, and
(by Grice's maxim of quantity,) therefore better. In it's form:

M: Safer is better.
m: Gary's assumption is safer.
C: Gary's assumption is better.

There are two empirical claims, specifically the major and minor
premises. It's not clear that either is true, but I think it's a
mistake to make a blanket judgment of net safety between competing
goods.

Long story short, it's safe for our pride, by cutting down outsiders,
but it's not safe for our publicity.

As for the discussion, Gary said it: 'self.list = self.list + [i]' is
a private write, but has other dangers such as running time and stored
references.

However, in my (opined) interpretation, 'list.append(...) is an in-
place operation' is a factual error. In-place operations -also-
rebind their 'argument' (FLOBW for lack of better words). 'append' is
a by-side-effect operation. However colloquially it's mostly
accurate.

And to the OP, your method works for immutable class members, and even
certain uses of mutable ones.

M R A Barnett

unread,
Mar 15, 2009, 1:27:43 PM3/15/09
to pytho...@python.org
Aaron Brady wrote:
[snip]

> However, in my (opined) interpretation, 'list.append(...) is an in-
> place operation' is a factual error. In-place operations -also-
> rebind their 'argument' (FLOBW for lack of better words). 'append' is
> a by-side-effect operation. However colloquially it's mostly
> accurate.
>
[snip]
All the augmented assignments rebind, even for objects which support
in-place operations. For example:

my_list = []
my_list += [0]

rebinds, but the equivalent:

my_list = []
my_list.extend([0])

doesn't.

Augmented assignments which don't support in-place operations behave
like normal assignments (binding). For example:

my_int = 0
my_int += 1

behaves like:

my_int = 0
my_int = my_int + 1

John Posner

unread,
Mar 15, 2009, 1:39:43 PM3/15/09
to pytho...@python.org

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

Given this class definition:

class Cls(object):
x = 345

... I observe the following, using IDLE 2.6.1:

>>> inst = Cls()
>>> Cls.x is inst.x
True

>>> Cls.x += 1
>>> Cls.x is inst.x
True

>>> inst.x += 1
>>> Cls.x is inst.x
False

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?

Tx,
John


Aaron Brady

unread,
Mar 15, 2009, 1:55:25 PM3/15/09
to

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

If you write an attribute, you want it stored in the attribute, not
the class or base classes.

...unless you're just picking on the augmented ops, in which case the
tradeoff is more subtle than stated.

Rhodri James

unread,
Mar 15, 2009, 2:50:04 PM3/15/09
to pytho...@python.org
On Sun, 15 Mar 2009 17:55:25 -0000, Aaron Brady <casti...@gmail.com>
wrote:

> On Mar 15, 12:39 pm, John Posner <jjpos...@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.

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

Matthew Woodcraft

unread,
Mar 15, 2009, 4:54:17 PM3/15/09
to
John Posner <jjpo...@snet.net> writes:

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

I doubt it's because anyone particularly wanted this behaviour; it just
falls out of the way '+=' is defined.

At the point where 'inst.x += 1' is compiled, Python doesn't know
whether 'inst.x' is going to turn out to be a class attribute or an
instance attribute or a property. So really the only thing it can do is
generate code to read inst.x in the usual way and then assign to inst.x
in the usual way (where 'the usual way' for CPython is LOAD_ATTR and
STORE_ATTR).

-M-

Bruno Desthuilliers

unread,
Mar 15, 2009, 3:56:55 PM3/15/09
to
Rhodri James a écrit :

> On Sun, 15 Mar 2009 17:55:25 -0000, Aaron Brady <casti...@gmail.com>
> wrote:
>
>> On Mar 15, 12:39 pm, John Posner <jjpos...@snet.net> wrote:
(snip)

>>> 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",

How would you resolve inst.method, then ?

> 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.
>
> Is there any actual advantage to self.attribute picking up
> Class.attribute instead of raising a NameError?

Yes: resolving methods and other descriptors.

Matthew Woodcraft

unread,
Mar 15, 2009, 4:58:16 PM3/15/09
to
"Rhodri James" <rho...@wildebst.demon.co.uk> writes:

> 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.
>
> Is there any actual advantage to self.attribute picking up
> Class.attribute instead of raising a NameError?

You use that any time you call an ordinary method using syntax like
'self.foo()'.

-M-

Bruno Desthuilliers

unread,
Mar 15, 2009, 4:06:58 PM3/15/09
to
John Posner a écrit :

> (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
> ...
>
> Given this class definition:
>
> class Cls(object): x = 345
>
> ... I observe the following, using IDLE 2.6.1:
>
>>>> inst = Cls() Cls.x is inst.x
> True
>
>>>> Cls.x += 1 Cls.x is inst.x
> True
>
>>>> inst.x += 1 Cls.x is inst.x
> False
>
> My question is ... WHY does the interpreter silently create the
> instance attribute at this point,

Becaause that's how you create instance attributes in Python. Why do you
think 'self' - that is, a reference to some object - is mandatory in
"methods" (really, functions) arguments list ?

Or do you mean that the existence of a synonym class attribute should be
checked on each instance variable assignement ? This would probably be a
big performance hit, and it would make per-instance method overloading
impossible (remember that OOP is about objects, not classes).

R. David Murray

unread,
Mar 15, 2009, 5:42:26 PM3/15/09
to pytho...@python.org
M R A Barnett <p...@mrabarnett.plus.com> wrote:
> Aaron Brady wrote:
> [snip]

> > However, in my (opined) interpretation, 'list.append(...) is an in-
> > place operation' is a factual error. In-place operations -also-
> > rebind their 'argument' (FLOBW for lack of better words). 'append' is
> > a by-side-effect operation. However colloquially it's mostly
> > accurate.
> >
> [snip]
> All the augmented assignments rebind, even for objects which support
> in-place operations. For example:
>
> my_list = []
> my_list += [0]
>
> rebinds, but the equivalent:
>
> my_list = []
> my_list.extend([0])
>
> doesn't.

Lest someone be mislead by this discussion, how about an example:

>>> a = b = []
>>> a.extend([1])
>>> a
[1]
>>> b
[1]
>>> a += [3]
>>> a
[1, 3]
>>> b
[1, 3]
>>> a = a + [5]
>>> a
[1, 3, 5]
>>> b
[1, 3]

It is technically correct that '+=' bebinds 'a', but what it
rebinds it to is the same object that was just mutated. Unlike
the '+' case where 'a' is bound to a newly created list object.

Personally I think += and kin were a bad idea and should have been
removed in Python 3.0 :) Even though I occasionally use them. (Maybe
I'll stop.)

> Augmented assignments which don't support in-place operations behave
> like normal assignments (binding). For example:
>
> my_int = 0
> my_int += 1
>
> behaves like:
>
> my_int = 0
> my_int = my_int + 1

--
R. David Murray http://www.bitdance.com

John Posner

unread,
Mar 15, 2009, 7:07:51 PM3/15/09
to pytho...@python.org

Matthew Woodcraft said:

> I doubt it's because anyone particularly wanted this
> behaviour; it just
> falls out of the way '+=' is defined.
>
> At the point where 'inst.x += 1' is compiled,
> Python doesn't know
> whether 'inst.x' is going to turn out to be a class
> attribute or an
> instance attribute or a property. So really the only thing
> it can do is
> generate code to read inst.x in the usual way and then
> assign to inst.x
> in the usual way (where 'the usual way' for CPython
> is LOAD_ATTR and
> STORE_ATTR).

That sounds reasonable to me.


Matthew Woodcraft also said:

>> Is there any actual advantage to self.attribute picking up
>> Class.attribute instead of raising a NameError?

> You use that any time you call an ordinary method using syntax like
> 'self.foo()'.

Yes, but that's performing a read (and call) operation on an attribute. My question concerned itself with potential confusion when you perform a write operation on an attribute.


Bruno Desthuilliers said:

>> My question is ... WHY does the interpreter silently create the
>> instance attribute at this point,

> Becaause that's how you create instance attributes in Python. Why do you
> think 'self' - that is, a reference to some object - is mandatory in
> "methods" (really, functions) arguments list ?

> Or do you mean that the existence of a synonym class attribute should be
> checked on each instance variable assignement ? This would probably be a

> big performance hit, ...

Yes, Bruno, I'm persuaded by this argument. Ideally, I'd like the interpreter to prevent the programmer from shooting him/herself in the foot, but it's not worth the performance hit.

> and it would make per-instance method overloading
> impossible (remember that OOP is about objects, not classes).

Yes again. While I was writing the above comment ("write operation on an attribute"), it *did* cross my mind that you might want to write self.attribute, even if it names a method, not a data-item.


Summary: I no longer suspect that "Python is broken". I *do* think that there's a situation that is potentially quite confusing:

* In the statement "self.x = self.x + 1", the two "self.x" names can sometimes refer to different objects.

* Even worse, in the equivalent statement "self.x += 1", the single name "self.x" can sometimes refer to two different objects!

I think this situation should be handled in documentation. (I'm a tech writer in my day job ... oh wait, I forgot ... I got laid off from my day job in December.) I'll look into what the standard Python doc set says on this matter.

-John

Aaron Brady

unread,
Mar 15, 2009, 7:26:04 PM3/15/09
to
On Mar 15, 1:50 pm, "Rhodri James" <rho...@wildebst.demon.co.uk>
wrote:
> On Sun, 15 Mar 2009 17:55:25 -0000, Aaron Brady <castiro...@gmail.com>  

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?

R. David Murray

unread,
Mar 15, 2009, 10:20:12 PM3/15/09
to pytho...@python.org
John Posner <jjpo...@snet.net> wrote:
> Summary: I no longer suspect that "Python is broken". I *do* think that
> there's a situation that is potentially quite confusing:
>
> * In the statement "self.x = self.x + 1", the two "self.x" names can
> sometimes refer to different objects.

But this is fundamental to Python. The name (or slot, in the case of say
a slice assignment) on the left hand side is being given a new binding
by the assignment statement. So whatever object the 'self.x' on the
left hand side may have pointed to before the statement is executed is
irrelevant (if we ignore '+=' and kin). That is the essence of assignment
in Python. If you are surprised by this, then you should probably study
up a bit on the way namespaces work in Python.

What I think you meant is that even though both are represented by the
same token sequence in the source ('self.x'), the two 'x's are actually
located in two different namespaces. The one on the left hand side of
the assignment is local to the instance, while the one on the right hand
side can cascade upward to the class namespace and resolve to an object
from there.

> * Even worse, in the equivalent statement "self.x += 1", the single name
> "self.x" can sometimes refer to two different objects!

Now on this one I'll agree with you about the "worse" part. Consider:

>>> class A(object):
... x = [1]
... def f(self):
... self.x = self.x + [2]
... print self.x
...
>>>
>>> m = A()
>>> m.f()
[1, 2]
>>> A.x
[1]
>>> class B(object):
... x = [1]
... def g(self):
... self.x += [2]
... print self.x
...
>>> n = B()
>>> n.g()
[1, 2]
>>> B.x
[1, 2]

I'm inclined to call that a problem, myself, even though I understand
why it happens (+= mutates the object pointed to by the class variable
'x', and _then_ the instance variable 'x' is created and pointed at the
same object. Whereas in the '+' case, a new list is created and the new
'x' instance variable is pointed at that new list.)

There is a somewhat analogous situation with variables in the local scope of
a function and global variables in the module. For example, we might have:

>>> x = 1
>>> def f():
... print x
...
>>> f()
1

So, when 'x' isn't found locally, the value gets picked up from the global
namespace. The difference from the class/instance case is when we try
to assign to it:

>>> def g():
... x = x + 1
...
>>> g()


Traceback (most recent call last):
File "<stdin>", line 1, in <module>

File "<stdin>", line 2, in g
UnboundLocalError: local variable 'x' referenced before assignment
>>> x = []
>>> def g():
... x += [1]
...
>>> g()


Traceback (most recent call last):
File "<stdin>", line 1, in <module>

File "<stdin>", line 2, in g
UnboundLocalError: local variable 'x' referenced before assignment

So in this case Python is warning us about the namespace difference.

Why are the two cases handled differently? To tell you the truth, I'm
not sure. I've been programming in Python for years and it just seems
to make sense to me to do it that way. It does allow you to use class
variables as default values for instance variables, as long as you are
careful when using mutable objects. But you could argue that it should
behave in a way analogous to local/global. It would be interesting to
see that argument laid out in full, with all the consequences it would
entail examined.

> I think this situation should be handled in documentation. (I'm a tech writer
> in my day job ... oh wait, I forgot ... I got laid off from my day job in
> December.) I'll look into what the standard Python doc set says on this
> matter.

Doc patches are always welcome, and from what I hear easier to get
accepted than code patches ;)

John Posner

unread,
Mar 15, 2009, 10:42:42 PM3/15/09
to pytho...@python.org

Earlier, I said:

> I'll look into what the standard Python doc set says on this
> matter.
>

RTFM, in section "Augmented assignment statements" of python301.chm:

---
For targets which are attribute references, the initial value is retrieved with a getattr() and the result is assigned with a setattr(). Notice that the two methods do not necessarily refer to the same variable. When getattr() refers to a class variable, setattr() still writes to an instance variable. For example:

class A:
x = 3 # class variable
a = A()
a.x += 1 # writes a.x as 4 leaving A.x as 3
---

So, this case is closed ... almost. I believe a similar explanation, with a similar example, should appear in the preceding/parent section, "Assignment statements". Here's my proposed example:

class A:
x = 3 # class variable
a = A()
a.x = a.x + 1 # a.x on RHS gets value of class variable (3)
# a.x on LHS creates instance variable with
value of RHS expression (4)

Others' thoughts on this?

-John

Rhodri James

unread,
Mar 15, 2009, 10:54:41 PM3/15/09
to pytho...@python.org
On Sun, 15 Mar 2009 23:26:04 -0000, Aaron Brady <casti...@gmail.com>
wrote:

> On Mar 15, 1:50 pm, "Rhodri James" <rho...@wildebst.demon.co.uk>


> wrote:
>> On Sun, 15 Mar 2009 17:55:25 -0000, Aaron Brady <castiro...@gmail.com>  
>> wrote:
>>
>> > On Mar 15, 12:39 pm, John Posner <jjpos...@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.

Tim Wintle

unread,
Mar 16, 2009, 12:02:09 AM3/16/09
to pytho...@python.org
On Sun, 2009-03-15 at 10:39 -0700, John Posner 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 ...

> Is there a beneficial effect of silently creating the instance attribute, which outweighs the detrimental effects: (1) inconsistency, (2) the "surprising" decoupling?

>From an end-user point of view (rather than the point of accessing class
methods others mentioned), here are two more reasons:

1) To save memory - there's only one object stored, where an instance
variable will require the same memory every instance (normally)


2) referencing Zope objects (although any persistent object storage will
have the same argument):

(Zope is a web framework that stores data as instances of python classes
in a persistent database.)

let's say you have the class (missing all the boilerplate)

{{{
class ZMyUser():
def __init__(self):
self.lookuplanguage = {\
"EN": "English"
}
self.language = "EN"

def get_friendly_name(self):
return self.lookuplanguage.get(self.language,"--")
}}}

And you create loads of these objects. But then you want to add French
as an option. How do you do that? All the objects have already been
created, so you could either:

* Run through every object in the database one by one and update the
dict as a one-off task (potentially taking a very long time as you force
the computer to pull the entire database off disk)

* Have written lookuplanguage as a class property, so re-initialising
the class will update the definition without any extra overhead.


Tim Wintle

unread,
Mar 16, 2009, 12:06:59 AM3/16/09
to pytho...@python.org
On Mon, 2009-03-16 at 04:02 +0000, Tim Wintle wrote:
> On Sun, 2009-03-15 at 10:39 -0700, John Posner wrote:

Doh, reply out of thread there - I meant to reply to Rhodi's comment
further down.

Gary Herron

unread,
Mar 16, 2009, 1:10:46 AM3/16/09
to pytho...@python.org
John Posner 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 ...
>
> Given this class definition:
>
> class Cls(object):
> x = 345
>
> ... I observe the following, using IDLE 2.6.1:
>
>
>>>> inst = Cls()
>>>> Cls.x is inst.x
>>>>
> True
>
>
>>>> Cls.x += 1
>>>> Cls.x is inst.x
>>>>
> True
>
>
>>>> inst.x += 1
>>>> Cls.x is inst.x
>>>>
> False
>
> 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?
>

I wouldn't call it "silently" because "inst.x = ..." is quite explicit
about "x" being an attribute of "inst". The rules for creating a
variable are simple and very consistent.

Each of
Cls.x = ...
inst.x = ...
x = ...
will create a variable (if it does not already exist) in a class,
instance or local name space respectively.

Retrieving a value is more complex as Python may look through several
namespaces in succession to find a value: (For example, inst.x will
check the instance , then the class ...)

The problem here is that
inst.x += 1
is really
inst.x = inst.x+1
which according to those rules, (if inst.x is not yet defined)
has both an instance and a class reference in the same statement.

After that, x.inst is defined in the instance, so both sides refer to that.

Gary Herron


> Tx,
> John
>
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Gary Herron

unread,
Mar 16, 2009, 2:34:06 AM3/16/09
to pytho...@python.org
John Posner wrote:
> Matthew Woodcraft said:
>
>
>> I doubt it's because anyone particularly wanted this
>> behaviour; it just
>> falls out of the way '+=' is defined.
>>
>> At the point where 'inst.x += 1' is compiled,
>> Python doesn't know
>> whether 'inst.x' is going to turn out to be a class
>> attribute or an
>> instance attribute or a property. So really the only thing
>> it can do is
>> generate code to read inst.x in the usual way and then
>> assign to inst.x
>> in the usual way (where 'the usual way' for CPython
>> is LOAD_ATTR and
>> STORE_ATTR).
>>
>
> That sounds reasonable to me.
>
>
> Matthew Woodcraft also said:
>
>
>>> Is there any actual advantage to self.attribute picking up
>>> Class.attribute instead of raising a NameError?
>>>
>
>
>> You use that any time you call an ordinary method using syntax like
>> 'self.foo()'.
>>
>
> Yes, but that's performing a read (and call) operation on an attribute. My question concerned itself with potential confusion when you perform a write operation on an attribute.
>
>
> Bruno Desthuilliers said:
>
>
>>> My question is ... WHY does the interpreter silently create the
>>> instance attribute at this point,
>>>
>
>
>> Becaause that's how you create instance attributes in Python. Why do you
>> think 'self' - that is, a reference to some object - is mandatory in
>> "methods" (really, functions) arguments list ?
>>
>
>
>> Or do you mean that the existence of a synonym class attribute should be
>> checked on each instance variable assignement ? This would probably be a
>> big performance hit, ...
>>
>
> Yes, Bruno, I'm persuaded by this argument. Ideally, I'd like the interpreter to prevent the programmer from shooting him/herself in the foot, but it's not worth the performance hit.
>
>
>> and it would make per-instance method overloading
>> impossible (remember that OOP is about objects, not classes).
>>
>
> Yes again. While I was writing the above comment ("write operation on an attribute"), it *did* cross my mind that you might want to write self.attribute, even if it names a method, not a data-item.
>
>
> Summary: I no longer suspect that "Python is broken". I *do* think that there's a situation that is potentially quite confusing:
>
> * In the statement "self.x = self.x + 1", the two "self.x" names can sometimes refer to different objects.
>
> * Even worse, in the equivalent statement "self.x += 1", the single name "self.x" can sometimes refer to two different objects!
>
> I think this situation should be handled in documentation. (I'm a tech writer in my day job ... oh wait, I forgot ... I got laid off from my day job in December.) I'll look into what the standard Python doc set says on this matter.
>

What's broken here is trying to have a class variable and an instance
variable of the same name and expecting Python to get it right.

Both of these problems become non-issues if you follow the "best
practice" for defining instance variables:

That is, set instance variables to their initial value in the __init__
method. And if you need a class default value, name it differently:

For example:

class C:
default_x = 123

def __init__(self):
self.x = self.default_x

def inc(self):
self.x += 1 // behaves as expected

Then self.x or inst=C() and inst.x will always refer to a instance
variable, the code is clear, and no confusion ensues.

Gary Herron

> -John
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Aaron Brady

unread,
Mar 16, 2009, 5:31:59 AM3/16/09
to
On Mar 15, 9:54 pm, "Rhodri James" <rho...@wildebst.demon.co.uk>
wrote:
> On Sun, 15 Mar 2009 23:26:04 -0000, Aaron Brady <castiro...@gmail.com>  

Very valid. Evidently I thought that the 'how' would justify it.
However, a *WHAT* in this case is pretty close to a 'why'.

You can access instance attributes and class attributes with the same
syntax. It has the advantage that you can mix two statements into
one:

attr= x.attr
<====>
if 'attr' in x.__dict__:
attr= x.__dict__[ 'attr' ]
else:
attr= x.__class__.__dict__[ 'attr' ]

Otherwise, either /1, every instance has its own entries for class
functions, and subsequent changes to the class don't affect existing
instances, or /2, every method call is of the form x.__class__.foo
( ). They're both bad. (...unless that's a false dilemma.)

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

No. What makes it obvious is that subsequent changes to the class
affect existing instances.

> 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 more space efficient. However, the additional time involved in
the 'instance-first-class-second' search, plus the process of creating
the bound method (once per access, by the way, currently), can
counterweigh or outweigh that.

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

No, I did leave some of the steps to the analysis tacit. My mistake.

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

As above, the alternatives (explicit class access and redundant
instance membership) are bad.

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

I know... that was just a tactic to get you to do the work of
enumerating the alternatives. Bah.

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

It's not. If you assign a function to an instance attribute, the
lookup doesn't extend to the class dictionary.

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

You can store in instances and classes, but you need different syntax
to specify which one you want. You can use the same syntax to read
from them. However, the syntax for accessing an instance member, and
forgoing the search to class and bases, is more complicated. I guess
the designer just figured that that wouldn't be very common.

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

Um, I don't remember exactly... even -with- my exact words in front of
me. Probably, there's no fallback to the class to check for
attributes, but there is no dynamic addition to instances or classes.
It's an example of, "everything's in the instance".

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

Convenience and economy, mostly.

a) duck.quack( )
b) duck.__class__.quack( )
c) Duck.quack( duck )

'a' is the most convenient, and it's more common to want it to succeed
with that meaning than fail; and there's still a way to get it to fail
anyway.

The underlying principle involved is somewhat delicate to achieve:
make everything possible, and the common easy.

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

P.S. Do you pronounce 'wildebeeste' like 'vildebeeste'?

Rhodri James

unread,
Mar 16, 2009, 7:28:20 PM3/16/09
to pytho...@python.org
On Mon, 16 Mar 2009 09:31:59 -0000, Aaron Brady <casti...@gmail.com>
wrote:
[snippety snip]

> Otherwise, either /1, every instance has its own entries for class
> functions, and subsequent changes to the class don't affect existing
> instances, or /2, every method call is of the form x.__class__.foo
> ( ). They're both bad. (...unless that's a false dilemma.)

I must admit I was envisaging a horribly inefficient (in space terms)
version of (1) in which the instance entries were binding stubs that
referenced the class entries, but that still falls over when new
methods get dynamically added to the class. I blame having two hours
of sleep in three days for this particular bit of dimness, sorry.

> P.S. Do you pronounce 'wildebeeste' like 'vildebeeste'?

No, with a "w" not a "v". It's just one of those titles that
stick with you no matter what you do.

Aahz

unread,
Mar 24, 2009, 7:11:40 PM3/24/09
to
In article <mailman.1847.1237048...@python.org>,

Maxim Khitrov <mkhi...@gmail.com> wrote:
>
>Very simple question on the preferred coding style. I frequently write
>classes that have some data members initialized to immutable values.
>For example:
>
>class Test(object):
> def __init__(self):
> self.some_value = 0
> self.another_value = None
>
>Similar effect can be achieved by defining some_value and
>another_value for the entire class, like so:
>
>class Test(object):
> some_value = 0
> another_value = None
>
>The advantage of doing this is that the assignments are evaluated once
>and thus the creation of that class is a bit faster. Access is still
>performed through self.some_value and self.another_value. Is there a
>reason to prefer the first style over the second?

Well, as you can see from reading this whole thread, it can be the source
of some confusion. Nevertheless, I personally sometimes use the style of
initializing at the class level. I think it's probably worth creating a
style guide entry for this issue if you're using Python for your
employer.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"At Resolver we've found it useful to short-circuit any doubt and just
refer to comments in code as 'lies'. :-)"
--Michael Foord paraphrases Christian Muirhead on python-dev, 2009-3-22

John Posner

unread,
Mar 25, 2009, 9:36:47 PM3/25/09
to pytho...@python.org

Following is a draft of my proposed addendum to the "Assignment statements"
section of the Python documentation (for both Python 2 and Python 3). I've
included reStructured Text markup. The first paragraph is what's already in
the documentation. Everything else is mine:

* If the target is an attribute reference: The primary expression in
the reference is evaluated. It should yield an object with
assignable attributes; if this is not the case, TypeError is raised.
That object is then asked to assign the assigned object to the given
attribute; if it cannot perform the assignment, it raises an
exception (usually but not necessarily AttributeError).

If the object is a class instance and the attribute reference occurs
on both sides of the assignment operator; for example::

self.x = self.x + 1

... in the RHS expression, ``self.x`` is evaluated with
``getattr()``, which can access either an instance attribute or (if
no instance attribute exists) a class attribute. The LHS target
``self.x`` is assigned with ``setattr()``, which *always* accesses
an instance attribute, creating it if necessary. Thus, the two
occurrences of ``self.x`` do not necessarily refer to the same
variable. If the RHS expression refers to a class attribute, the LHS
creates a new instance attribute as the target of the assignment.

See section "Augmented assignment statements" for a similar note on
attribute references.


If anyone would like to suggest changes to this write-up, have at it. I plan
to submit a SourceForge issue within a day or so.

(BTW, I searched through the existing issues, to see if it has already been
reported. AFAIK, it hasn't. But #4246 is a cousin, referencing
UnboundLocalError exceptions.

-John

E-mail message checked by Spyware Doctor (6.0.0.386)
Database version: 5.12040
http://www.pctools.com/en/spyware-doctor-antivirus/

Steve Holden

unread,
Mar 25, 2009, 11:27:44 PM3/25/09
to pytho...@python.org

Is this true in the case of read-write properties? This seems a little
simplistic for what's actually a pretty complex piece of logic.

> occurrences of ``self.x`` do not necessarily refer to the same
> variable. If the RHS expression refers to a class attribute, the LHS
> creates a new instance attribute as the target of the assignment.
>
> See section "Augmented assignment statements" for a similar note on
> attribute references.
>
>
> If anyone would like to suggest changes to this write-up, have at it. I plan
> to submit a SourceForge issue within a day or so.
>
> (BTW, I searched through the existing issues, to see if it has already been
> reported. AFAIK, it hasn't. But #4246 is a cousin, referencing
> UnboundLocalError exceptions.
>

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
Want to know? Come to PyCon - soon! http://us.pycon.org/

John Posner

unread,
Mar 26, 2009, 11:47:14 PM3/26/09
to Steve Holden, pytho...@python.org
[snip]

>> > If the object is a class instance and the attribute reference
occurs
>> > on both sides of the assignment operator; for example::
>> >
>> > self.x = self.x + 1
>> >
>> > ... in the RHS expression, ``self.x`` is evaluated with
>> > ``getattr()``, which can access either an instance attribute or
(if
>> > no instance attribute exists) a class attribute. The LHS target
>> > ``self.x`` is assigned with ``setattr()``, which *always* accesses

>> > an instance attribute, creating it if necessary. Thus, the two

Steve Holden said:

>> Is this true in the case of read-write properties? This
>> seems a little
>> simplistic for what's actually a pretty complex piece of logic.

It's not true for the read-write property example in the official property()
function description:

class C(object):
def __init__(self):
self._x = None

def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")


But it *is* true if you revise this class definition to follow the pattern
under discussion: a class attribute provides the "initial value" of an
instance attribute:

class C(object):
_x = 0

def __init__(self):
pass
def getx(self):
return self._x
def setx(self, value):
self._x = value
x = property(getx, setx)


My intent was to fix an obvious omission: a special case was discussed in
the "Augmented assignment statements" section, but an almost-identical
special case was omitted from the "Assignment statements" section.

Neither section currently mentions property attributes. Do you think both
sections should be changed to cover property attributes? Or maybe it would
be simpler just to revise my first sentence:

from: If the object is a class instance
to: If the object is a (non-property) class instance

E-mail message checked by Spyware Doctor (6.0.0.386)

Database version: 5.12050
http://www.pctools.com/en/spyware-doctor-antivirus/

Steve Holden

unread,
Mar 27, 2009, 2:47:40 AM3/27/09
to John Posner, pytho...@python.org
That amendment would probably be least confusing to new readers, though
it would help when in hypermedia to link "property" to some discussion
of properties as they apply on the various Python versions.

John Posner

unread,
Mar 31, 2009, 10:52:12 AM3/31/09
to Steve Holden, pytho...@python.org
I said:

>> > My intent was to fix an obvious omission: a special case
>> was discussed in
>> > the "Augmented assignment statements" section, but an
>> almost-identical
>> > special case was omitted from the "Assignment statements" section.

After finally getting registered at bugs.python.org (as described in another
thread), I submitted my suggested change to the Python documentation. It's
issue 5621.

-John

E-mail message checked by Spyware Doctor (6.0.0.386)

Database version: 5.12080
http://www.pctools.com/en/spyware-doctor-antivirus/

0 new messages