Class properties and object properties

Diez B. Roggisch deets at nospam.web.de
Mon Oct 6 15:29:55 CEST 2008


SuperZE wrote:

> Learning python I was rewriting some of my old programs to see the
> pros and cons of python when a steped in some weird (at least for me)
> behavior.
> 
> Here it is simplified
> 
> The code:
> 
>>>> class Test1:
> myList = [4 for n in range(4)]
> myInt = 4
>>>> a = Test1()
>>>> b = Test1()
>>>> a.myList
> [4, 4, 4, 4]
>>>> a.myInt
> 4
>>>> b.myList
> [4, 4, 4, 4]
>>>> b.myInt
> 4
>>>> b.myList[2] = 3
>>>> b.myInt = 3
>>>> b.myList
> [4, 4, 3, 4]
>>>> b.myInt
> 3
>>>> a.myList
> [4, 4, 3, 4]
>>>> a.myInt
> 4
> 
> 
> I would not expect the second a.myList to have changed as it did
> since, for me, I have only changed b.myList. And also, why only the
> list changed and not the integer?
> 
> One thing i tried was:
> 
>>>> class Test2:
> myList = []
> myInt = 4
> def __init__(self):
> self.myList = [4 for n in range(4)]
> 
>>>> a = Test2()
>>>> b = Test2()
>>>> a.myList
> [4, 4, 4, 4]
>>>> b.myList
> [4, 4, 4, 4]
>>>> b.myList[2] = 3
>>>> b.myList
> [4, 4, 3, 4]
>>>> a.myList
> [4, 4, 4, 4]
> 
> 
> And as you see it worked as I expected.
> 
> Now the question, why?

Because you declare myList to be a *class*-level variable, which means *all*
instances of that class (a and b in your case) *share* it. Python does not
declare *instance* variables the way you do.

Instead, do this:

class Foo(object):
    def __init__(self):
        self.myList = []

And to avoid a common pitfall you are likely to hit next: default arguments
in functions (and methods) are evaluated only *once*, when defined - not
later!

So

def foo(some_arg=[]):
    some_arg.append("a")
    print some_arg

foo()
foo()

will result in 

['a']
['a', 'a'] 

being printed out.

Diez



More information about the Python-list mailing list