How to Avoid Having Class Data Shared Among Instances

How to avoid having class data shared among instances?

You want this:

class a:
def __init__(self):
self.list = []

Declaring the variables inside the class declaration makes them "class" members and not instance members. Declaring them inside the __init__ method makes sure that a new instance of the members is created alongside every new instance of the object, which is the behavior you're looking for.

class variables is shared across all instances in python?

var should definitely not be shared as long as you access it by instance.var or self.var. With the list however, what your statement does is when the class gets evaluated, one list instance is created and bound to the class dict, hence all instances will have the same list. Whenever you set instance.list = somethingelse resp. self.list = somethingelse, it should get an instance level value.

Example time:

>>> class A():
... var = 0
... list = []
...
>>> a = A()
>>> b = A()
>>> a.var
0
>>> a.list
[]
>>> b.var
0
>>> b.list
[]
>>> a.var = 1
>>> b.var
0
>>> a.list.append('hello')
>>> b.list
['hello']
>>> b.list = ['newlist']
>>> a.list
['hello']
>>> b.list
['newlist']

Why do two class instances appear to be sharing the same data?

You fell into a common newbie trap for Python. Using a list as a default variable as you did with def __init__(self, list = [0,0,0,0,0,0,0,0,0,0]) means that all instances of that class share the same list instance as the value for that argument. See also "Least Astonishment" and the Mutable Default Argument

By the way, a common idiom if you want to use a container object such as a list as a default argument, is to instead use None and check for that. For example:

def __init__(self, values=None):
if values is None:
values = [0] * 10

Or whatever. Not quite as clearly self-documenting as default arguments but it works.

As a side note, don't use list as a variable name, as it shadows the (somewhat commonly used) list builtin.

Why do multiple instances of a Python object behave as if they were the same?

SimulationResults.results is a class attribute shared by all instances. Make it an instance attribute instead.

class SimulationResults:
def __init__(self):
self.results = []

def append(self,n):
self.results.append(n)

Are multiple class instances sharing this list?

The b variable is assigned at the top level the class, so it is a class variable. That means that you always see the same list object regardless of which instance you access it through (or if you access it through the class directly, as a.b).

If you want a separate list in each instance, create the variable with an assignment to an attribute of self in an __init__ method:

class a:
def __init__(self):
self.b = []

Are the attributes in a Python class shared or not?

The difference is that in your second example you are creating a new list, self.tricks, as an attribute of the object:

def __init__(self,name):
self.name=name
self.tricks=[name] # <-- this is creating the new attribute for the object
self.tricks.append(name)

The first example works because of Python's way of resolving the names: If self.tricks cannot be found in the object (because it hasn't been created), then it tries to find it as a member of the class. Since tricks is there, then you can access it.

It may become clear to you if you try to use mytest.tricks in your second example:

def __init__(self,name):
self.name=name
mytest.tricks=[name] # <-- this is accesing the class attribute instead
self.tricks.append(name)

That will output what you are actually expecting.

is there any downside to creating lots of class instances?

My advice would be to first optimise for readability and maintainability of your code. Focus on performance only when it demonstrably becomes an issue. Once you know it's an issue, you'll be able to measure the system in its entirety, identify bottlenecks and fix them.

You may find that:

  • performance isn't an issue at all; or
  • it is an issue, but the bottleneck isn't at all where you thought it would be (from experience, this happens all the time).

With this in mind, I would favour the first approach over the second.

Share variable between instances of the same class in python

Assigning a value to self.shared_variable makes self.shared_variable an instance attribute so that the value is not shared among instances.

You can instead assign the value explicitly to the class attribute by referencing the attribute of the instance's class object instead.

Change:

self.shared_variable = paremeter_optional

to:

self.__class__.shared_variable = paremeter_optional

Python: How to share data between instances of different classes?

You are correct, in your case inheritance does not make sense. But, how about explicitly passing the objects during the instantiation. This would make a lot of sense.

Something like:

Class BigClassA:
def __init__(self):
..
Class BigClassB:
def __init__(self, objA):
self.b = objA.b
self.c = objA.c
self.d = objA.d

Class BigClassC:
def __init__(self, objA, objB):
self.b = objA.b # need value of b from BigClassA
self.f = objB.f # need value of f from BigClassB

While instantiating, do:

objA = BigClassA()
..
objB = BigClassB(objA)
..
objC = BigClassC(objA, objB)


Related Topics



Leave a reply



Submit