My problem looks something like this.
# Module.py
class TestClass:
name = "default"
nameDict = {'name':"standard"}
def __init__(self, name):
self.name = name
self.nameDict['name'] = name
Then I call on the fields from another module. The class is initiated before and I call on the name field like this:
Module.TestClass("newName")
# Inside another function
print(Module.TestClass.name)
print(Module.TestClass.nameDict['name'])
Which gives:
default #name
newName #nameDict
I don't understand why it would be different values. Does anyone have any idea why this would happen?
Thanks for your time.
There are two ways to access a single value of a dictionary: The square brackets [] approach. The safer get() method.
With CPython 2.7, using dict() to create dictionaries takes up to 6 times longer and involves more memory allocation operations than the literal syntax. Use {} to create dictionaries, especially if you are pre-populating them, unless the literal syntax does not work for your case.
This is an interesting question; there's a lot going on.
Module.TestClass
is the class you've defined in 'Module.py'. With Module.TestClass("newName")
, you're creating an instance of that class, but you're not saving it.
When you do print(Module.TestClass.name)
, you're printing the value of the name
attribute of Module.TestClass
, which is the class, not an instance of the class. The name
you gave the instance before doesn't change the class' name
attribute.
The really interesting bit is print(Module.TestClass.nameDict['name'])
. Even though you're still accessing the nameDict
attribute of the class, it is affected by the instance you created earlier. This is because Python variables hold references to objects. When you defined the class, you assigned a dictionary to the attribute nameDict
in the class scope. That exact same dictionary object is being pointed at by the class and all the instances of the class. So, if you change it in one place, it's changed everywhere, because it's actually the exact same dict.
Here's a good way to do what it looks like you're trying to do:
# Module.py
class TestClass(object):
def __init__(self, name='default'):
self.name = name
self.nameDict = {'name': name}
# other.py
testclass_instance = Module.TestClass("newName")
# Inside another function
print(testclass_instance.name) # newName
print(testclass_instance.nameDict['name']) # newName
The difference you are seeing is because -
Strings are immutable , whereas dictionaries are mutable .
In your init function , when you do - self.name = name - this creates assigns a new reference to name in your instance , that does not change the reference that the class variable name holds .
In your init function , when you change the value for the name key in the dictionary , you are mutating the dictionary (which is the same dictionary for the class variable) , hence it reflects in the class variable dictionary as well. If you had assigned a new dictionary here , you would be able to see the old value in the class variable still.
This basically happens because when you create an instance , the class variables' reference are copied as such to the instance, the reference still pointing to whatever class variable pointed to at that time. Since in this case, as the reference is same the changes to dict reflect in the class variable.
But when you do assignment, you are making the variable point to a new reference, and this does not cause the class variable to change.
A simple example to show this -
>>> class CA:
... d = [1,2]
...
>>> CA.d
[1, 2]
>>> c = CA()
>>> c.d
[1, 2]
>>> id(c.d) == id(CA.d)
True
>>> c.d.append(3)
>>> CA.d
[1, 2, 3]
>>> c.d = [1,2,3,4,5]
>>> CA.d
[1, 2, 3]
>>> CA.d = [1,2,3,4,5,6]
>>> CA.d
[1, 2, 3, 4, 5, 6]
>>> d = CA()
>>> d.d
[1, 2, 3, 4, 5, 6]
>>> c.d
[1, 2, 3, 4, 5]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With