By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,757 Members | 1,201 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,757 IT Pros & Developers. It's quick & easy.

direct initialization of class attributes vs. declarations w/in __init__

P: n/a
What's the difference between initializing class variables within the
class definition directly versus initializing them within the class's
__init__ method? Is there a reason, perhaps in certain situations, to
choose one over the other?

Thank you.

Jun 11 '06 #1
Share this Question
Share on Google+
16 Replies


P: n/a
di*************@gmail.com schrieb:
What's the difference between initializing class variables within the
class definition directly versus initializing them within the class's
__init__ method? Is there a reason, perhaps in certain situations, to
choose one over the other?


You are confusing class variables with instance variables. The former
are what you can initialize inside the class-statement. However, they
are shared amongst _all_ instances. Consider this little example:

class Foo(object):
FOO = 1
BAR = []

def __init__(self, FOO):
self.FOO = FOO
self.BAR.append(FOO)

def __repr__(self):
return "FOO: %r\nBAR: %r\n" % (self.FOO, self.BAR)
f1 = Foo(1)
print f1
f2 = Foo(2)
print f2
print f1
------
meskal:~/Projects/CameraCalibrator deets$ python2.4 /tmp/test.py
FOO: 1
BAR: [1]

FOO: 2
BAR: [1, 2]

FOO: 1
BAR: [1, 2]
-----

As you can see, the list BAR is shared. And you can also see that
_assigning_ to something like this:

self.FOO

will create an instance-variable. Even if a variable of the same name
existed on the class before!

Which is precisely the difference between using variable initialization
in __init__ and inside the class-statement.

BTW,

self.__class__.FOO = value

will set class-variables inside a method. Just if you wondered.

Diez
Jun 11 '06 #2

P: n/a
Ah, you've brought me much clarity Diez, thank you. That would explain
some "bugs" I've been having...
Diez B. Roggisch wrote:
di*************@gmail.com schrieb:
What's the difference between initializing class variables within the
class definition directly versus initializing them within the class's
__init__ method? Is there a reason, perhaps in certain situations, to
choose one over the other?


You are confusing class variables with instance variables. The former
are what you can initialize inside the class-statement. However, they
are shared amongst _all_ instances. Consider this little example:

class Foo(object):
FOO = 1
BAR = []

def __init__(self, FOO):
self.FOO = FOO
self.BAR.append(FOO)

def __repr__(self):
return "FOO: %r\nBAR: %r\n" % (self.FOO, self.BAR)
f1 = Foo(1)
print f1
f2 = Foo(2)
print f2
print f1
------
meskal:~/Projects/CameraCalibrator deets$ python2.4 /tmp/test.py
FOO: 1
BAR: [1]

FOO: 2
BAR: [1, 2]

FOO: 1
BAR: [1, 2]
-----

As you can see, the list BAR is shared. And you can also see that
_assigning_ to something like this:

self.FOO

will create an instance-variable. Even if a variable of the same name
existed on the class before!

Which is precisely the difference between using variable initialization
in __init__ and inside the class-statement.

BTW,

self.__class__.FOO = value

will set class-variables inside a method. Just if you wondered.

Diez


Jun 11 '06 #3

P: n/a
Wait a minute! It doesn't explain my bugs. I've got "class variables"
acting like instance variables. What's weirder is that this behavior
occurs on my computer (in both of my installed WinXP copies) but not on
my laptop (WinXP Pro).

See the following test:

class Boo:
jerk = "yes"

def killjerk(self):
self.jerk = self.jerk + "no"
print self.jerk
print self.__class__.jerk

bing = Boo()
bing.killjerk()

outputs:

yesno
yes

At first, I thought that self.jerk was resolving to the class attribute
instead of creating a new variable (w/ a differing scope). But we can
see that there are actually two variables because a direct reference to
self.__class__.jerk returns "yes", not yesno (what we would get if
self.jerk pointed to the same data/object as self.__class__.jerk). Yet,
it's treating self.jerk as a combination of the two (it always add the
class attribute to the instance attribute). Is this normal behavior??
It doesn't work this way on my laptop...

Perhaps you can see why I'd be confused!

Thanks.

di*************@gmail.com wrote:
Ah, you've brought me much clarity Diez, thank you. That would explain
some "bugs" I've been having...
Diez B. Roggisch wrote:
di*************@gmail.com schrieb:
What's the difference between initializing class variables within the
class definition directly versus initializing them within the class's
__init__ method? Is there a reason, perhaps in certain situations, to
choose one over the other?


You are confusing class variables with instance variables. The former
are what you can initialize inside the class-statement. However, they
are shared amongst _all_ instances. Consider this little example:

class Foo(object):
FOO = 1
BAR = []

def __init__(self, FOO):
self.FOO = FOO
self.BAR.append(FOO)

def __repr__(self):
return "FOO: %r\nBAR: %r\n" % (self.FOO, self.BAR)
f1 = Foo(1)
print f1
f2 = Foo(2)
print f2
print f1
------
meskal:~/Projects/CameraCalibrator deets$ python2.4 /tmp/test.py
FOO: 1
BAR: [1]

FOO: 2
BAR: [1, 2]

FOO: 1
BAR: [1, 2]
-----

As you can see, the list BAR is shared. And you can also see that
_assigning_ to something like this:

self.FOO

will create an instance-variable. Even if a variable of the same name
existed on the class before!

Which is precisely the difference between using variable initialization
in __init__ and inside the class-statement.

BTW,

self.__class__.FOO = value

will set class-variables inside a method. Just if you wondered.

Diez


Jun 11 '06 #4

P: n/a
di*************@gmail.com wrote:
At first, I thought that self.jerk was resolving to the class attribute
instead of creating a new variable (w/ a differing scope).
When you access an instance attribute, Python first looks in the
instance object, and then in the class object.

When you assign to an instance attribute, it's *always* assigned to the
instance object, whether there's a class attribute with the same name or
not.

If there's already a class attribute with the same name, that attribute
will be shadowed (but can still be accessed via the class object, of
course).
It doesn't work this way on my laptop...


Python's always worked that way, so I find that a bit hard to believe.

</F>

Jun 11 '06 #5

P: n/a

Fredrik Lundh wrote:
di*************@gmail.com wrote:
At first, I thought that self.jerk was resolving to the class attribute
instead of creating a new variable (w/ a differing scope).


When you access an instance attribute, Python first looks in the
instance object, and then in the class object.

When you assign to an instance attribute, it's *always* assigned to the
instance object, whether there's a class attribute with the same name or
not.

If there's already a class attribute with the same name, that attribute
will be shadowed (but can still be accessed via the class object, of
course).
It doesn't work this way on my laptop...


Python's always worked that way, so I find that a bit hard to believe.


No need to be obnoxious. I do appreciate your efforts to help, but you
must admit, your last statement is a bit snide and certainly not
useful. I'm telling you that the code runs differently on my laptop.
Why this is, I don't know any more /or/ less than you do apparently.
Now, it is of course possible that I'm interpreting the results
incorrectly, but that doesn't change the fact that I'm getting
different results per computer with identical code.

Jun 11 '06 #6

P: n/a
Thank you Dennis, this makes the behavior so much clearer to me. I see
now that when self.jerk = self.jerk + 1 is executed that even though
the names are identical, at this point I'm referring to two different
values (one which is being created in part from the other).

As for my laptop, I'm not really sure what's up there. I can change the
class variable self.jerk all I want but it has no influence over the
instance variable. Here's the code:

class Boo:
jerk = 10

def killjerk(self):
self.jerk += 1
print self.jerk
print self.__class__.jerk

bing = Boo()
bing.killjerk()

On my desktop, I get:

11
10

On my laptop, I get:

1
10

Now, if I remove the class variable, I get an AttributeError, as you'd
expect. This happens on both the desktop and laptop. However, on the
laptop it seems not to care what value I give the class variable jerk,
it only requires that it exist. Any clue what's behind this behavior?
I'm running the same python version on both computers (the ActiveState
distro).

Thanks for all the help...
Dennis Lee Bieber wrote:
On 11 Jun 2006 10:35:14 -0700, di*************@gmail.com declaimed the
following in comp.lang.python:
Wait a minute! It doesn't explain my bugs. I've got "class variables"
acting like instance variables. What's weirder is that this behavior
occurs on my computer (in both of my installed WinXP copies) but not on
my laptop (WinXP Pro).

Don't know about the laptop but...
See the following test:

See the following modified version:

-=-=-=-=-=-=-
class Boo:
jerk = "yes"

def killjerk(self):
print id(self.jerk), id(self.__class__.jerk)
self.jerk = self.jerk + "no"
print self.jerk, id(self.jerk)
print self.__class__.jerk

bing = Boo()
bing.killjerk()
bing.killjerk()
-=-=-=-=-=-=-=-
10837696 10837696
yesno 18264128
yes
18264128 10837696
yesnono 18289600
yes

The initial lookup for "self.jerk" does not find it in the instance,
so it looks higher, into the class.

THEN when you "assign" the result to "self.jerk" you create an
instance specific name entry, which is bound to a string at a different
location. The lookup on the left side does not go outside of the
instance. Notice how the second "bing.killjerk()" results in "self.jerk"
being bound to a third address.

--
Wulfraed Dennis Lee Bieber KD6MOG
wl*****@ix.netcom.com wu******@bestiaria.com
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: we******@bestiaria.com)
HTTP://www.bestiaria.com/


Jun 11 '06 #7

P: n/a
di*************@gmail.com wrote:
Any clue what's behind this behavior?


a missing plus sign.

</F>

Jun 11 '06 #8

P: n/a
Fredrik Lundh wrote:
a missing plus sign.


or a misplaced one... (=+ 1 is not the same thing as += 1)

</F>

Jun 11 '06 #9

P: n/a

Fredrik Lundh wrote:
di*************@gmail.com wrote:
Any clue what's behind this behavior?


a missing plus sign.

</F>


Thanks for the guess but not possible given the following:

class Boo:
jerk = 10

def killjerk(self):
counter = 3
while counter !=0:
counter -= 1
self.jerk += 1
print self.jerk
print self.__class__.jerk
bing = Boo()
bing.killjerk()

Output from desktop comp.:
11
10
12
10
13
10

Output from laptop comp.:

1
10
2
10
3
10

?? . . .

Jun 11 '06 #10

P: n/a
> No need to be obnoxious. I do appreciate your efforts to help, but you
must admit, your last statement is a bit snide and certainly not
useful.
I'm telling you that the code runs differently on my laptop.
It certainly doesn't. There is absolutely no imaginable way how this
behavior could be different, even if the python versions would differ
considerably. Apart from quantum-fluctuations. Or other SciFi voodoo.
Why this is, I don't know any more /or/ less than you do apparently.
Frederik (as one of the most profiled python developers out there) might
not be the most amicable of posters, but he certainly is not wrong when
it comes to the most basic parts of python's semantics.
Now, it is of course possible that I'm interpreting the results
incorrectly, but that doesn't change the fact that I'm getting
different results per computer with identical code.


It is NOT identical code, otherwise you won't see different
results. It might be code from which you _believe_ it is identical, and
the difference might be subtle to see. But if you'd store it in a file,
execute on your laptop, use an usb-stick and then transfer it to
whatever the other machine of yours is, it will yield the exact same
results.

Diez
Jun 11 '06 #11

P: n/a
di*************@gmail.com wrote:
Output from laptop comp.:

1
10
2
10
3
10


so how are you entering and running the code on your laptop ?

what happens if you set the class attribute to 100 instead of 10 ?

</F>

Jun 11 '06 #12

P: n/a
Oh wow, I wasn't expecting so much help. I really appreciate it. My
problem, however, has been solved. I uninstalled my ActiveState Python
distro on my laptop and installed the distro from python.org along with
Stan's Python Editor. I ran the same code I'd run before and guess
what? The behavior now matches that of my desktop! Why? *shrug*

As for the code being identical, it certainly was as I emailed the .py
file to myself (from the laptop) and downloaded it to my desktop where
I then ran it just as I had done on the laptop, with PythonWin. Unless
Google programmed Gmail to muck w/ people's python code....
Additionally, the bytes on the files match. Thus, I feel I can
guarantee that the code is indeed identical.

Here's my wild guess: for some reason a bug in PythonWin was causing my
changes to the class attribute (i.e. jerk variable) not to be reflected
in the actual code. This explanation, if you can call it one, still
doesn't make sense to me however because I could make other changes to
the code and it would indeed be reflected in execution. Add to the fact
that PythonWin is essentially just a text editor, I don't see how/why
it would selectively save code changes.

It is true that I never restarted the PythonWin IDE after a change of
the class attribute to something other than 0, and perhaps reinstalling
python etc. was unnecessary. I'm only coming to this realization now.

In any event, I am now problem free and quite pleased to be able to
exchange .py files between computers and know they'll behave the same
(rather, I'm assuming this henceforth).

Furthermore, I'd like to thank everyone who tried to help, and that
certainly includes Fredrik.
Cheers,

DigiO

Jun 12 '06 #13

P: n/a

Fredrik Lundh wrote:
di*************@gmail.com wrote:
Output from laptop comp.:

1
10
2
10
3
10


so how are you entering and running the code on your laptop ?

what happens if you set the class attribute to 100 instead of 10 ?

</F>


You can see my other post which I just sent but, I was using PythonWin:

1. type code in editor
2. hit run
3. observe output in interactive window

Jun 12 '06 #14

P: n/a

Diez B. Roggisch wrote:
No need to be obnoxious. I do appreciate your efforts to help, but you
must admit, your last statement is a bit snide and certainly not
useful.
> I'm telling you that the code runs differently on my laptop.
It certainly doesn't. There is absolutely no imaginable way how this
behavior could be different, even if the python versions would differ
considerably. Apart from quantum-fluctuations. Or other SciFi voodoo.


Hmmm
Why this is, I don't know any more /or/ less than you do apparently.
Frederik (as one of the most profiled python developers out there) might
not be the most amicable of posters,


Although he dropped what I perceived to be a snide and unhelpful
comment, two things. One, I understand what's behind it in the sense
that the behavior I was describing goes against the semantic
fundamentals of python, and should therefore be impossible. Two,
Fredrik is no doubt a sweetheart and he showed it by continuing to put
his efforts toward helping me despite my criticism of him. I can't
thank him enough. Honestly, I believe newsgroups need more people like
him . . .

...

It is NOT identical code, otherwise you won't see different
results. It might be code from which you _believe_ it is identical, and
the difference might be subtle to see. But if you'd store it in a file,
execute on your laptop, use an usb-stick and then transfer it to
whatever the other machine of yours is, it will yield the exact same
results.

Diez


Read my other post. The code was/is definitely identical. In any event,
I don't really care. It's working properly now, and if I have similarly
weird problems in future, I'll deal with them at that time. I don't
know what was up, but I understand it doesn't make sense from any
visible standpoint of logic. Thank you for your efforts Diez...

Jun 12 '06 #15

P: n/a
di*************@gmail.com wrote:
Fredrik Lundh wrote:
di*************@gmail.com wrote:

Output from laptop comp.:

1
10
2
10
3
10


so how are you entering and running the code on your laptop ?

what happens if you set the class attribute to 100 instead of 10 ?

</F>

You can see my other post which I just sent but, I was using PythonWin:

1. type code in editor
2. hit run
3. observe output in interactive window

Frankly I'd be less incredulous if you'd said you transferred the code
between machines using some network- or file-based transfer mechanism.
The facts are that if you have been entering "the same" code separately
on two machines then by far the most likely source of any discrepancy is
typographical error (a subject with which regular readers will know I am
intimately familiar).

The Python behaviour you now understand (access to class variables in
the absence of an eponymous instance variable) is long-standing, and it
is therefore unlikely that two correct Python installations will give
different results for the same code. Ergo, the two pieces of code are
different.

Unless, that is, you can tell us different beyond all possibility of
transcription errors.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Love me, love my blog http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Jun 12 '06 #16

P: n/a
di*************@gmail.com wrote:
[...]
Read my other post. The code was/is definitely identical. In any event,
I don't really care. It's working properly now, and if I have similarly
weird problems in future, I'll deal with them at that time. I don't
know what was up, but I understand it doesn't make sense from any
visible standpoint of logic. Thank you for your efforts Diez...

It would be nice to know where the discrepancy arose, but now I see you
were using email to transfer the source code I happily withdraw my
accusations of typographical error.

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Love me, love my blog http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Jun 12 '06 #17

This discussion thread is closed

Replies have been disabled for this discussion.