class object's attribute is also the instance's attribute?

Discussion in 'Python' started by 陈伟, Aug 30, 2012.

  1. when i write code like this:

    class A(object):

    d = 'it is a doc.'


    t = A()

    print t.__class__.d
    print t.d

    the output is same.

    so it means class object's attribute is also the instance's attribute. is it right? i can not understand it.
     
    陈伟, Aug 30, 2012
    #1
    1. Advertising

  2. 陈伟

    Marco Nawijn Guest

    On Thursday, August 30, 2012 12:55:25 PM UTC+2, 陈伟 wrote:
    > when i write code like this:
    >
    >
    >
    > class A(object):
    >
    >
    >
    > d = 'it is a doc.'
    >
    >
    >
    >
    >
    > t = A()
    >
    >
    >
    > print t.__class__.d
    >
    > print t.d
    >
    >
    >
    > the output is same.
    >
    >
    >
    > so it means class object's attribute is also the instance's attribute. isit right? i can not understand it.


    I think the best way is to think of it as a global attribute restricted to the class A. Note that you even don't need an instance to get the value of the attribute. You can directly get it from the class itself.

    >>> class A(object): d = 'my attribute'
    >>> A.d

    'my attribute'
    >>> aobj = A()
    >>> aobj.d

    'my attribute'

    Note that if you change 'd' it will change for all instances!
    >>> bobj = A()
    >>> bobj.d

    'my attribute'

    >>> A.d = 'oops...attribute changed'
    >>> aobj.d

    'oops...attribute changed'

    >>> bobj.d

    'oops...attribute changed'

    If you want attributes to be local to the instance, you have to define themin the __init__ section of the class like this:

    class A(object):

    def __init__(self):
    d = 'my attribute'

    >>> aobj = A()
    >>> bobj = A()


    >>> aobj.d

    'my attribute'

    >>> bobj.d

    'my attribute'

    >>> aobj.d = 'oops...attribute changed'


    >>> aobj.d

    'oops...attribute changed'

    >>> bobj.d

    'my attribute'

    Regards,

    Marco
     
    Marco Nawijn, Aug 30, 2012
    #2
    1. Advertising

  3. On Thu, 30 Aug 2012 05:34:51 -0700 (PDT), Marco Nawijn
    <> wrote:
    > If you want attributes to be local to the instance, you have to

    define them in the __init__ section of the class like this:

    > class A(object):
    > def __init__(self):
    > d = 'my attribute'


    Except that in this case you'd need to do:
    self.d = 'my attribute'

    Oscar
     
    Oscar Benjamin, Aug 30, 2012
    #3
  4. 陈伟

    Hans Mulder Guest

    On 30/08/12 14:34:51, Marco Nawijn wrote:

    > Note that if you change 'd' it will change for all instances!


    That depends on how you change it.

    >>>> bobj = A()
    >>>> bobj.d

    > 'my attribute'
    >
    >>>> A.d = 'oops...attribute changed'


    Here you change the attribute on the class.
    That will affect all instances:

    >>>> aobj.d

    > 'oops...attribute changed'
    >
    >>>> bobj.d

    > 'oops...attribute changed'


    You can also set the attribute on an instance:

    >>> bobj.d = 'For bobj only'
    >>> bobj.d

    'For bobj only'
    >>>> aobj.d

    > 'oops...attribute changed'


    So, if you specifically change it on one instance, thenit won't
    change on other instances of the same class.

    > If you want attributes to be local to the instance, you have
    > to define them in the __init__ section of the class like this:


    That's a good idea, but it's not required. You can set them
    later, as shown above.


    > class A(object):
    >
    > def __init__(self):
    > d = 'my attribute'


    That will just set the global variable d.
    You want to set the instance attribute:

    self.d = 'my attribute'

    >>>> aobj = A()
    >>>> bobj = A()

    >
    >>>> aobj.d

    > 'my attribute'


    Note that aobj.d will not find the global variable d,
    if neither the instance, nor the class nor any of the
    base classes have that attribute.

    I don't know where this 'my attribute' comes from, but
    it's not the instance attribute you tried to set in the
    __init__ method. Maybe your class A still has a class
    attribute with that value from an earlier experiment.


    Hope this helps,

    -- HansM
     
    Hans Mulder, Aug 30, 2012
    #4
  5. 陈伟

    Marco Nawijn Guest

    On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:
    > On 30/08/12 14:34:51, Marco Nawijn wrote:
    >
    >
    >
    > > Note that if you change 'd' it will change for all instances!

    >
    >
    >
    > That depends on how you change it.
    >
    >
    >
    > >>>> bobj = A()

    >
    > >>>> bobj.d

    >
    > > 'my attribute'

    >
    > >

    >
    > >>>> A.d = 'oops...attribute changed'

    >
    >
    >
    > Here you change the attribute on the class.
    >
    > That will affect all instances:
    >
    >
    >
    > >>>> aobj.d

    >
    > > 'oops...attribute changed'

    >
    > >

    >
    > >>>> bobj.d

    >
    > > 'oops...attribute changed'

    >
    >
    >
    > You can also set the attribute on an instance:
    >
    >
    >
    > >>> bobj.d = 'For bobj only'

    >
    > >>> bobj.d

    >
    > 'For bobj only'
    >
    > >>>> aobj.d

    >
    > > 'oops...attribute changed'

    >
    >
    >
    > So, if you specifically change it on one instance, thenit won't
    >
    > change on other instances of the same class.
    >
    >
    >
    > > If you want attributes to be local to the instance, you have

    >
    > > to define them in the __init__ section of the class like this:

    >
    >
    >
    > That's a good idea, but it's not required. You can set them
    >
    > later, as shown above.
    >
    >
    >
    >
    >
    > > class A(object):

    >
    > >

    >
    > > def __init__(self):

    >
    > > d = 'my attribute'

    >
    >
    >
    > That will just set the global variable d.
    >
    > You want to set the instance attribute:
    >
    >
    >
    > self.d = 'my attribute'
    >
    >
    >
    > >>>> aobj = A()

    >
    > >>>> bobj = A()

    >
    > >

    >
    > >>>> aobj.d

    >
    > > 'my attribute'

    >
    >
    >
    > Note that aobj.d will not find the global variable d,
    >
    > if neither the instance, nor the class nor any of the
    >
    > base classes have that attribute.
    >
    >
    >
    > I don't know where this 'my attribute' comes from, but
    >
    > it's not the instance attribute you tried to set in the
    >
    > __init__ method. Maybe your class A still has a class
    >
    > attribute with that value from an earlier experiment.
    >
    >
    >
    >
    >
    > Hope this helps,
    >
    >
    >
    > -- HansM


    Learned my lesson today. Don't assume you know something. Test it first ;).I have done quite some programming in Python, but did not know that class attributes are still local to the instances. It is also a little surprisingI must say. I always considered them like static variables in C++ (not that I am an expert in C++).

    I knew of course that you don't have to define a local attribute in the __init__ method of a class, but I consider it good style and since the OP is aself claimed newbie I left out the other option.

    The missing "self" in the code below was a typo
    class A(object):

    def __init__(self):
    d = 'my attribute' # should be self.d

    Regards,

    Marco
     
    Marco Nawijn, Aug 30, 2012
    #5
  6. 陈伟

    Dave Angel Guest

    On 08/30/2012 10:11 AM, Marco Nawijn wrote:
    > On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:
    >> <snip>
    >>

    > Learned my lesson today. Don't assume you know something. Test it first ;). I have done quite some programming in Python, but did not know that class attributes are still local to the instances.


    They're not. They're just visible to the instances, except where the
    instance has an instance attribute of the same name. Don't be confused
    by dir(), which shows both instance and class attributes.

    Please show me an example where you think you observe each instance
    getting a copy of the class attribute. There's probably some other
    explanation.




    --

    DaveA
     
    Dave Angel, Aug 30, 2012
    #6
  7. 陈伟

    Marco Nawijn Guest

    On Thursday, August 30, 2012 4:30:59 PM UTC+2, Dave Angel wrote:
    > On 08/30/2012 10:11 AM, Marco Nawijn wrote:
    >
    > > On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:

    >
    > >> <snip>

    >
    > >>

    >
    > > Learned my lesson today. Don't assume you know something. Test it first ;). I have done quite some programming in Python, but did not know that class attributes are still local to the instances.

    >
    >
    >
    > They're not. They're just visible to the instances, except where the
    >
    > instance has an instance attribute of the same name. Don't be confused
    >
    > by dir(), which shows both instance and class attributes.
    >
    >
    >
    > Please show me an example where you think you observe each instance
    >
    > getting a copy of the class attribute. There's probably some other
    >
    > explanation.


    I don't have an example. It was just what I thought would happen. Consider the following. In a class declaration like this:

    class A(object):
    attr_1 = 10

    def __init__(self):
    self.attr_2 = 20

    If I instantiated it twice:

    obj_1 = A()
    obj_2 = A()

    For both obj_1 and obj_2 attr_1 equals 10. What I thought would happen after the following statement:

    obj_1.attr_1 = 12

    is that obj_2.attr_1 also equals 12. This is what surprised me a little, that's all.

    Marco
     
    Marco Nawijn, Aug 30, 2012
    #7
  8. 陈伟

    Marco Nawijn Guest

    On Thursday, August 30, 2012 4:30:59 PM UTC+2, Dave Angel wrote:
    > On 08/30/2012 10:11 AM, Marco Nawijn wrote:
    >
    > > On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:

    >
    > >> <snip>

    >
    > >>

    >
    > > Learned my lesson today. Don't assume you know something. Test it first ;). I have done quite some programming in Python, but did not know that class attributes are still local to the instances.

    >
    >
    >
    > They're not. They're just visible to the instances, except where the
    >
    > instance has an instance attribute of the same name. Don't be confused
    >
    > by dir(), which shows both instance and class attributes.
    >
    >
    >
    > Please show me an example where you think you observe each instance
    >
    > getting a copy of the class attribute. There's probably some other
    >
    > explanation.


    I don't have an example. It was just what I thought would happen. Consider the following. In a class declaration like this:

    class A(object):
    attr_1 = 10

    def __init__(self):
    self.attr_2 = 20

    If I instantiated it twice:

    obj_1 = A()
    obj_2 = A()

    For both obj_1 and obj_2 attr_1 equals 10. What I thought would happen after the following statement:

    obj_1.attr_1 = 12

    is that obj_2.attr_1 also equals 12. This is what surprised me a little, that's all.

    Marco
     
    Marco Nawijn, Aug 30, 2012
    #8
  9. 陈伟

    Dave Angel Guest

    On 08/30/2012 10:48 AM, Marco Nawijn wrote:
    > On Thursday, August 30, 2012 4:30:59 PM UTC+2, Dave Angel wrote:
    >> On 08/30/2012 10:11 AM, Marco Nawijn wrote:
    >>
    >>> On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:

    >>
    >>>> <snip>

    >>
    >>>>

    >>
    >>> Learned my lesson today. Don't assume you know something. Test it first ;). I have done quite some programming in Python, but did not know that class attributes are still local to the instances.

    >>
    >>
    >>
    >> They're not. They're just visible to the instances, except where the
    >>
    >> instance has an instance attribute of the same name. Don't be confused
    >>
    >> by dir(), which shows both instance and class attributes.
    >>
    >>
    >>
    >> Please show me an example where you think you observe each instance
    >>
    >> getting a copy of the class attribute. There's probably some other
    >>
    >> explanation.

    >
    > I don't have an example. It was just what I thought would happen. Consider the following. In a class declaration like this:
    >
    > class A(object):
    > attr_1 = 10
    >
    > def __init__(self):
    > self.attr_2 = 20
    >
    > If I instantiated it twice:
    >
    > obj_1 = A()
    > obj_2 = A()
    >
    > For both obj_1 and obj_2 attr_1 equals 10. What I thought would happen after the following statement:
    >
    > obj_1.attr_1 = 12
    >
    > is that obj_2.attr_1 also equals 12. This is what surprised me a little, that's all.
    >
    > Marco
    >


    That statement only adds an instance attribute, not modifying the class
    attribute of the same name. But it does "hide" it from that particular
    instance.

    The thing that can be surprising is that if the class attribute is
    mutable, and you mutate it, rather than assigning it. So for example:

    class A(object):
    attr_1 = [10, 9]

    def __init__(self):
    self.attr_2 = 20


    obj_1 = A()
    obj_2 = A()

    obj_1.attr_1.append(3)

    Then I believe you'll see [10, 9, 3] from both instances.
    print obj_1.attr_1
    print obj_2.attr_1



    --

    DaveA
     
    Dave Angel, Aug 30, 2012
    #9
  10. 陈伟

    Hans Mulder Guest

    On 30/08/12 16:48:24, Marco Nawijn wrote:
    > On Thursday, August 30, 2012 4:30:59 PM UTC+2, Dave Angel wrote:
    >> On 08/30/2012 10:11 AM, Marco Nawijn wrote:
    >>> On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:
    >>>> <snip>


    >>> Learned my lesson today. Don't assume you know something. Test it first ;).


    A very important lesson.

    Next week's lesson will be: if you test it first, then
    paste it into a message for this forum, then tweak just
    one unimportant detail, you'll need to test it again.

    >>> I have done quite some programming in Python, but did not know that

    class
    >>> attributes are still local to the instances.


    >> They're not. They're just visible to the instances, except where the
    >> instance has an instance attribute of the same name. Don't be confused
    >> by dir(), which shows both instance and class attributes.
    >>
    >> Please show me an example where you think you observe each instance
    >> getting a copy of the class attribute. There's probably some other
    >> explanation.

    >
    > I don't have an example. It was just what I thought would happen.
    > Consider the following. In a class declaration like this:
    >
    > class A(object):
    > attr_1 = 10
    >
    > def __init__(self):
    > self.attr_2 = 20
    >
    > If I instantiated it twice:
    >
    > obj_1 = A()
    > obj_2 = A()
    >
    > For both obj_1 and obj_2 attr_1 equals 10. What I thought would happen after the following statement:
    >
    > obj_1.attr_1 = 12
    >
    > is that obj_2.attr_1 also equals 12. This is what surprised me a little, that's all.


    The trick is to look at obj_1.__dict__ to see what is defined locally:

    >>> obj_1 = A()
    >>> obj_1.__dict__

    {'attr_2': 20}

    >>> obj_1.attr_1 = 12
    >>> obj_1.__dict__

    {'attr_2': 20, 'attr_1': 12}


    Hope this helps,

    -- HansM
     
    Hans Mulder, Aug 30, 2012
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sridhar R
    Replies:
    14
    Views:
    1,424
    =?iso-8859-1?Q?Fran=E7ois?= Pinard
    Feb 10, 2004
  2. Donnal Walter

    class attribute to instance attribute

    Donnal Walter, Jun 30, 2005, in forum: Python
    Replies:
    4
    Views:
    482
    Greg Ewing
    Jul 6, 2005
  3. Russell Warren
    Replies:
    5
    Views:
    486
    Russell Warren
    Jan 17, 2006
  4. Daniel Lipovetsky
    Replies:
    2
    Views:
    351
    Jordan Greenberg
    Mar 12, 2007
  5. Marc Aymerich
    Replies:
    11
    Views:
    233
    Steven D'Aprano
    Nov 23, 2012
Loading...

Share This Page