I was working with two instances of a python class when I realize they where using the same values. I think I have a missunderestanding of what classes are used for.
A much simpler example:
class C():
def __init__(self,err = []):
self.err = err
def add(self):
self.err.append(0)
a = C()
print(a.err) # []
a.add()
print(a.err) # [0]
b = C()
print(b.err) # [0]
b.add()
print(a.err) # [0,0]
print(b.err) # [0,0]
I don't underestand why b.err starts as [0] instead of []. And why when adding an element to b it affects a too.
CodePudding user response:
The reason is here:
def __init__(self,err = []):
default err
value is saved inside class C
. But err
itself is mutable, so every time you append anything to it, next time it will have stored value and this default err
value is saved as a.err
and b.err
:
a = C()
print(a.err) # a.err is err ([])
a.add()
print(a.err) # err is [0]
b = C()
print(b.err) # reused err that is [0]
b.add() # err is [0, 0]
print(a.err) # [0,0]
print(b.err) # [0,0]
So basically err
inside a
and b
is the same
Article: https://florimond.dev/en/posts/2018/08/python-mutable-defaults-are-the-source-of-all-evil/
CodePudding user response:
I recommend that you check the Python core language features first. Check the official FAQs for Python 3, particularly https://docs.python.org/3/faq/programming.html#why-are-default-values-shared-between-objects is what you are looking for.
According to the recommendations, you have to change your code like so
from typing import List
class C():
def __init__(self,err: List = None):
self.err = [] if err is None else err
def add(self):
self.err.append(0)
a = C()
print(a.err) # []
a.add()
print(a.err) # [0]
b = C()
print(b.err) # []
b.add()
print(a.err) # [0]
print(b.err) # [0]
I will also link to the concept of mutability in the docs as it seems that this was the issue for OP: https://docs.python.org/3/glossary.html#term-mutable
CodePudding user response:
In here we want to identify a list is a mutable data structure in python. It is means we can change it as we want. Class is a blueprint of the object so after creating the object it should be working individually<- this is your question. yeah typically it is correct but in here thing is when we don't give the default value for after constructor parameters. It changes after we create an object. we want to determine the concept correctly.
code review given below,
a = C()
print(a.err) # [] #empty err list
a.add()
print(a.err) # append 0 into err list
b = C()
print(b.err) # after create object that create a showing you in here
b.add() #aappend another 0 to err list
print(a.err) # [0,0] #err list
print(b.err) # [0,0] #err list