Changing variables in multiple instances of Python

Is it necessary in any case to set the variables of all instances of the class? The following is a simplified example:

class Object(): def __init__(self): self.speed=0 instance0=Object() instance1=Object() instance2=Object() #Object.speed=5 doesn't work of course 

I see that this is possible by adding all new instances to the list and iterating with isinstance (), but this is undesirable.

+3
source share
4 answers

One, simpler way, like other answers, is to keep the attribute always as an attribute of the class. If it is installed in the class of the class, and all write access to the attribute is through the name of the class, and not the instance that will work:

 >>> class Object(object): ... speed = 0 ... >>> a = Object() >>> b = Object() >>> c = Object() >>> >>> Object.speed = 5 >>> print a.speed 5 >>> 

However, if you ever set an attribute in one instance that does it this way, the instance will have its own attribute, and it will no longer change with another instance:

 >>> a.speed = 10 >>> Object.speed = 20 >>> print b.speed 20 >>> print a.speed 10 >>> 

To overcome this, so that whenever the attribute is specified in any instance, the class attribute itself changes, the easier it is to have the object as a property whose setter sets the class attribute instead:

 class Object(object): _speed = 0 @property def speed(self): return self.__class__._speed @speed.setter def speed(self, value): self.__class__._speed = value 

What works:

 >>> >>> a = Object() >>> b = Object() >>> a.speed, b.speed (0, 0) >>> a.speed = 10 >>> a.speed, b.speed (10, 10) 

If you want to have an independent attribute for instances, but the special set_all method that would set the attribute in all instances, you can use the gc (Garbage Collector) module in the standard librayr to find and skip all instances of the class and set their instance attributes:

 import gc class Object(object): def __init__(self): self.speed = 0 def set_all_speed(self, value): for instance in (obj for obj in gc.get_referrers(self.__class__) if isinstance(obj, self.__class__)): instance.speed = value 

Result:

 >>> a =Object() >>> b = Object() >>> a.speed = 5 >>> b.speed = 10 >>> a.speed, b.speed (5, 10) >>> a.set_all_speed(20) >>> a.speed, b.speed (20, 20) 
+16
source

How about using a class attribute?

 class Object(): speed=0 instance0=Object() instance1=Object() instance2=Object() Object.speed=5 
+2
source

You can use the class attribute:

 class Object(): speed = 0 instance0=Object() instance1=Object() instance2=Object() Object.speed=5 # instance0.speed == instance1.speed == instance2.speed == Object.speed == 5 

However, this would mean that all instances would always have the same speed .

+2
source

"Is there a way to set the variables of all instances of the class at the same time ?

What a class attribute!

Some examples of accessing a class attribute:

 >>> class Object: ... speed = 5 ... @classmethod ... def first(cls): ... return cls.speed ... def second(self): ... return self.speed ... >>> Object.speed 5 >>> instance = Object() >>> instance.speed 5 >>> instance.first() 5 >>> instance.second() 5 
0
source

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


All Articles