Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Class properties and object properties

Reply
Thread Tools

Class properties and object properties

 
 
SuperZE
Guest
Posts: n/a
 
      10-06-2008
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?
 
Reply With Quote
 
 
 
 
Diez B. Roggisch
Guest
Posts: n/a
 
      10-06-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
 
Reply With Quote
 
 
 
 
SuperZE
Guest
Posts: n/a
 
      10-06-2008
> 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 = []



Interesting, but that does not explain the difference in the behavior
of myList and myInt

Both were class-level variables, as far as I can see, and therefor a
and b should also share it


And good remind on default arguments
 
Reply With Quote
 
Diez B. Roggisch
Guest
Posts: n/a
 
      10-06-2008
SuperZE wrote:

>> 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 = []

>
>
> Interesting, but that does not explain the difference in the behavior
> of myList and myInt


Sorry, I forgot that.

The reason is simple - lists are mutable. Numbers aren't. And when you
*assign* to an instance a value, it will be set on the instance, not on the
class.

The same happens (as you've already seen for yourself) when you do

a.myList = []

as this creates a new list, stored only on a.


> Both were class-level variables, as far as I can see, and therefor a
> and b should also share it


Nope. To change it, you need to do

Test1.myInt = 5

The thing is that the lookup triggered by getattr/dotted notation goes
roughly like this:

1) try to find the attribute (value *or* method! Python doesn't distinguish)
in the instance itself.

2) if not found there, look at the class.

3) if not found there, look at the base-classes in the method resolution
order (MRO)

There are some other things involved - descriptor protocol calls on the
class-level lookups - but that's not relevant for the problem at hand.

OTOH, when setting with setattr/dotted notation, it will always set on the
object passed.

Diez
 
Reply With Quote
 
Jerry Hill
Guest
Posts: n/a
 
      10-06-2008
On Mon, Oct 6, 2008 at 9:38 AM, SuperZE <(E-Mail Removed)> wrote:
> Interesting, but that does not explain the difference in the behavior
> of myList and myInt
>
> Both were class-level variables, as far as I can see, and therefor a
> and b should also share it


They did share it, until you assigned an instance variable in b, which
shadowed the class variable. Example:

>>> class Test1:

myInt = 4


>>> a = Test1()
>>> b = Test1()
>>> a.myInt

4
>>> b.myInt

4
>>> Test1.myInt

4
>>> b.myInt = 3
>>> a.myInt

4
>>> b.myInt

3
>>> Test1.myInt

4

As soon as you bound the name b.myInt to a new value, it created an
instance variable. That hides the value of Test1.myInt.

--
Jerry
 
Reply With Quote
 
SuperZE
Guest
Posts: n/a
 
      10-06-2008
TYVM Diez and Jerry

Now I understand how this works
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
While executing the class definition which object is referenced bythe first argument of the class method, Y r Object attributes not allowed asdefault arguments Krishna Python 4 03-07-2008 09:44 PM
Why 'class spam(object)' instead of class spam(Object)' ? Sergio Correia Python 7 09-18-2007 02:07 AM
Nested Class, Member Class, Inner Class, Local Class, Anonymous Class E11 Java 1 10-12-2005 03:34 PM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
Passing derived class object array in place of base class object array justanotherguy63@yahoo.com C++ 9 12-03-2004 10:57 PM



Advertisments