Class properties and object properties

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • SuperZE

    Class properties and object properties

    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?
  • Diez B. Roggisch

    #2
    Re: Class properties and object properties

    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

    Comment

    • SuperZE

      #3
      Re: Class properties and object properties

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

      Comment

      • Jerry Hill

        #4
        Re: Class properties and object properties

        On Mon, Oct 6, 2008 at 9:38 AM, SuperZE <allansuperze@g mail.comwrote:
        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

        Comment

        • SuperZE

          #5
          Re: Class properties and object properties

          TYVM Diez and Jerry

          Now I understand how this works

          Comment

          Working...