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

2012-08-30 Thread Ben Finney
Hans Mulder  writes:

> 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.

+1 QotW

-- 
 \“Look at it this way: Think of how stupid the average person |
  `\ is, and then realise half of 'em are stupider than that.” |
_o__)   —George Carlin, _Doin' It Again_, 1990 |
Ben Finney
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Oscar Benjamin
On 30 August 2012 15:11, Marco Nawijn  wrote:
>
>
> 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
> surprising I must say. I always considered them like static variables in
> C++ (not that I am an expert in C++).
>

Class attributes are analogous to static variables in C++ provided you only
ever assign to them as an attribute of the class.

>>> class A(object):
...   static = 5
...
>>> a = A()
>>> a.static
5
>>> A.static
5
>>> b = A()
>>> b.static
5
>>> A.static = 10
>>> a.static
10
>>> b.static
10

An instance attribute with the same name as a class attribute hides the
class attribute for that instance only.

>>> b.static = -1
>>> a.static
10
>>> b.static
-1
>>> del b.static
>>> b.static
10

This is analogous to having a local variable in a function that hides a
module level variable with the same name:

x = 10

def f1():
x = 4
print(x)

def f2():
print(x)

f2()  # 10
f1()  # 4
f2()  # still 10

If you want f1 to modify the value of x seen by f2 then you should
explicitly declare x as global in f1.

Likewise if you want to modify an attribute for all instances of a class
you should explicitly assign to the class attribute rather than an instance
attribute.

Oscar
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Hans Mulder
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:
 

>>> 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
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Dave Angel
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:
>>
 
>>

>>
>>> 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
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Marco Nawijn
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:
> 
> >> 
> 
> >>
> 
> > 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
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Dave Angel
On 08/30/2012 10:11 AM, Marco Nawijn wrote:
> On Thursday, August 30, 2012 3:25:52 PM UTC+2, Hans Mulder wrote:
>> 
>>
> 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

-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Marco Nawijn
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 surprising I 
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 a 
self 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
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Hans Mulder
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

-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread 陈伟
在 2012年8月30日星期四UTC+8下午7时54分35秒,Dave Angel写道:
> On 08/30/2012 06:55 AM, 陈伟 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. is 
> > it right? i can not understand it.
> 
> 
> 
> In your example, you have no instance attribute.  So when you use the
> 
> syntax to fetch one, the interpreter looks first at the instance,
> 
> doesn't find it, then looks in the class, and does.  That is documented
> 
> behavior.  Some people use it to provide a kind of default value for
> 
> instances, which can be useful if most instances need the same value,
> 
> but a few want to overrride it.
> 
> 
> 
> -- 
> 
> 
> 
> DaveA
thank you very much.

-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Oscar Benjamin
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

--
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Marco Nawijn
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. is it 
> 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 them in 
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
-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Ulrich Eckhardt

Am 30.08.2012 12:55, schrieb 陈伟:

class A(object):
 d = 'it is a doc.'

t = A()

print t.__class__.d
print t.d

the output is same.


You could go even further:

print id(t.__class__.d)
print id(t.d)

which should show you that they are not just equal but identical.



so it means class object's attribute is also the instance's
attribute.is it right?


Yes. This is even useful sometimes:

class Point(object):
x = 0
y = 0

This will cause every Point to have two attributes x and y that have a 
default value 0.



Note that setting this attribute on an instance does not change the 
class' attribute, just in that that was what confused you. However, if 
the attribute references a mutable type (e.g. a list) this can cause 
problems because the instance (see id() above) is the same and thus 
modifications affect both the class and all instances.



Uli

--
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread Dave Angel
On 08/30/2012 06:55 AM, 陈伟 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. is it 
> right? i can not understand it.

In your example, you have no instance attribute.  So when you use the
syntax to fetch one, the interpreter looks first at the instance,
doesn't find it, then looks in the class, and does.  That is documented
behavior.  Some people use it to provide a kind of default value for
instances, which can be useful if most instances need the same value,
but a few want to overrride it.

-- 

DaveA

-- 
http://mail.python.org/mailman/listinfo/python-list


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

2012-08-30 Thread 陈伟
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.
-- 
http://mail.python.org/mailman/listinfo/python-list