Could somebody please explain the following code to me.
class InnerTest:
def __init__(self, value = 0):
self.value = value
class OuterTest:
def __init__(self, inner_test = InnerTest()):
self.inner_test = inner_test
a = OuterTest()
b = OuterTest()
a.inner_test.value = 42
print b.inner_test.value
It prints 42, I expected 0.
I meant to create two instances of OuterTest, which would contain a distinct instance of InnerTest each. Instead I got two instances of OuterTest which reference the same instance of InnerTest.
Also what would be a correct way to implement what I wanted please?
Copy an Object in Python In Python, we use = operator to create a copy of an object. You may think that this creates a new object; it doesn't. It only creates a new variable that shares the reference of the original object.
Yes, you can use copy. deepcopy . so just c2 = copy. deepcopy(c) then vars(c2) == {'a': 11, 'r': 2} and vars(c) == {'a': 11, 'r': 2} but the traceback your are reporting wouldn't be produced by the class definition you gave...
__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .
To create instances of a class, you call the class using class name and pass in whatever arguments its __init__ method accepts.
The default parameter in functions are evaluated only once, at the time of function definition. So there is only one instance of InnerTest
being used for both the object.
That means, when you create the two objects:
a = OuterTest()
b = OuterTest()
Both, a.inner_test
and b.inner_test
, are referring to the same instance, and hence the result.
To solve this, change the default value to None
, and create instance conditionally:
class OuterTest:
def __init__(self, inner_test=None):
if not inner_test:
inner_test = InnerTest()
self.inner_test = inner_test
You could move the InnerTest()
into the init or call it in the init, passing a reference to the class n the second case.
Using def __init__(self, inner_test = InnerTest()):
is evaluated once so the object is shared among all instances of the OuterTest
class making it a class attribute as opposed to an instance attribute by instantiating it in the init.
class OuterTest:
def __init__(self):
self.inner_test = InnerTest()
Or:
class OuterTest:
def __init__(self, inner_test = InnerTest):
self.inner_test = inner_test()
Both methods will work as desired, passing a reference to a class means you have the option of passing in whatever class you want:
In [11]: class OuterTest:
....: def __init__(self, inner_test=InnerTest):
....: self.inner_test = inner_test()
....:
In [12]: a = OuterTest()
In [13]: b = OuterTest()
In [14]: a.inner_test.value = 42
In [15]: print(a.inner_test.value)
42
In [16]: print(b.inner_test.value)
0
In [17]: class OuterTest:
....: def __init__(self):
....: self.inner_test = InnerTest()
....:
In [18]: a = OuterTest()
In [19]: b = OuterTest()
In [20]: a.inner_test.value = 42
In [21]: print(a.inner_test.value)
42
In [22]: print(b.inner_test.value)
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