Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create distinct instances of a class in Python? [duplicate]

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?

like image 429
marcv81 Avatar asked Dec 15 '15 16:12

marcv81


People also ask

How do you duplicate a class object in Python?

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.

How do you copy an instance class in Python?

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...

What does __ class __ mean in Python?

__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 .

How do you create an instance of a class in Python?

To create instances of a class, you call the class using class name and pass in whatever arguments its __init__ method accepts.


2 Answers

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
like image 135
Rohit Jain Avatar answered Sep 27 '22 16:09

Rohit Jain


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)
like image 45
Padraic Cunningham Avatar answered Sep 27 '22 18:09

Padraic Cunningham