Class variables behave differently for list and int?

Class shared variables share all class instances as far as I know. But I'm having problems with my head.

class c(): a=[1] b=1 def __init__(self): pass x=c() xaappend(1) x.b+=1 #or xb=2 print xa #[1,1] print xb #2 y=c() print ya #[1,1] :As Expected print yb #1 :why not 2? 

ya resonates with xa , but yb does not work.

hope someone can clarify.

EDIT: And how to create the same functionality for ints.

+3
source share
2 answers
 xaappend(1) 

modifies the class attribute ca , a list , calling its append method, which modifies the list in place.

 xb += 1 

actually a shorthand for

 xb = xb + 1 

since integers in Python are immutable, so they don't have the __iadd__ method (in place). The result of this assignment is to set the attribute b in instance x with a value of 2 (the result of evaluating the right side of the task). This new instance attribute obscures the class attribute.

To see the difference between an on-site operation and an appointment, try

 xa += [1] 

and

 xa = xa + [1] 

They will have a different behavior.

EDIT . The same can be used for integers by putting them in a box:

 class HasABoxedInt(object): boxed_int = [0] # int boxed in a singleton list a = HasABoxedInt() a.boxed_int[0] += 1 b = HasABoxedInt() print(b.boxed_int[0]) # prints 1, not zero 

or

 class BoxedInt(object): def __init__(self, value): self.value = value def __iadd__(self, i): self.value += i 
+10
source
Answer to

larsmans is excellent, but it can provide additional information if we look at the id of xb before and after the appointment.

 class c(): a=[1] b=1 def __init__(self): pass x=c() print "initial a : {} at {}".format(xa, id(xa)) print "initial b : {} at {}".format(xb, id(xb)) xaappend(1) x.b+=1 # xb = xb + 1, created a new object # we created an instance variable xb and it # is shadowing the class variable b. print "after change a : {} at {}".format(xa, id(xa)) print "after change b : {} at {}".format(xb, id(xb)) y=c() # We can already see from the class object that # b has not changed value print "in class cb : {} at {}".format(cb, id(cb)) print "in instance ya : {} at {}".format(ya, id(ya)) print "in instance yb : {} at {}".format(yb, id(yb)) 

Result:

 initial a : [1] at 50359040 initial b : 1 at 40974280 after change a : [1, 1] at 50359040 after change b : 2 at 40974256 # Shows id of instance variable xb; hence it is # different in class cb : 1 at 40974280 in instance ya : [1, 1] at 50359040 in instance yb : 1 at 40974280 

If you want to use int as a class variable, this should work:

 class MyClass(object): b=1 def increase_b(self, n): MyClass.b += n 

Result:

 >>> mc_1 = MyClass() >>> mc_1.b 1 >>> mc_1.increase_b(5) >>> mc_1.b 6 >>> mc_2 = MyClass() >>> mc_2.b 6 >>> mc_2.increase_b(10) >>> MyClass.b 16 >>> mc_2.b 16 >>> mc_1.b 16 
+2
source

Source: https://habr.com/ru/post/1498733/


All Articles