-1
 class base:
    def __init__(self):
        self.x = [1, 2, 3]

        
class child1(base):
    def __init__(self):
        super().__init__()
        
    def __repr__(self):
        return str(self.x) + ' '+ str(id(self.x)) 
        

class child2(base):
    def __init__(self):
        super().__init__()
        
    def __repr__(self):
        return str(self.x) + ' ' + str(id(self.x))
        

a = child1()
b = child2()
code when self.x of base class mutable when self.x of base class is not mutable
print(a) [1, 2, 3] 140256922286752 1000 140256922840528
print(b) [1, 2, 3] 140256964882096 1000 140256922840528

My question is:
integers which are not in range from -5 to 256, will have different id.
But in my case self.x of for the child classes is same as base. which means they point to the same location.
But with an mutable object like list it is different, my question is, are both the lists copies(shallow) of base class list, or are they same. Also in general for python, do child class variables point to the same location in memory where the base class variable point?

Thank you for helping me out.

  • 1
    I don't think inheritance factors into this at all; you'd see the same behavior if you just had multiple instances of a single class. There's no reason for the interpreter to duplicate an immutable object so it makes sense that it'd shallow-copy in cases like this. – Samwise Dec 21 '20 at 16:03
  • The "member variables" don't belong to the class, this is not C++. An object has attributes. You object has attribute `x`. Whether you initialise it from the base class or not makes no difference at all. – zvone Dec 21 '20 at 16:04
  • Also, _"an immutable object like list"_? Lists are not immutable objects. – zvone Dec 21 '20 at 16:06
  • 1
    The only special thing here is that in a test which is not shown you used `1000` as value of `x` in two places. In both places, Python used the same instance of `1000`, because Python sometimes does that with integers, to save some space. – zvone Dec 21 '20 at 16:08
  • @Samwise sir it is not the case, suppose I assign x=1000 and y =1000, id of both these objects is different. I also checked for classes, if there is one more class that does not inheirt this base class than id of the immutable object is different. – satinder singh Dec 21 '20 at 16:08
  • @zvone I have corrected "an immutable object like list" – satinder singh Dec 21 '20 at 16:10
  • @zvone but why if I create a new class with a member variable x =1000, then why does it have a different id? – satinder singh Dec 21 '20 at 16:10
  • You should show how you tested your code with `1000`. My guess is the two variables did not exist in the same time, so they got the same address. But either way, it does not matter. Because `1000` is immutable, you should not care about whther the same instance is used or another one. – zvone Dec 21 '20 at 16:11
  • 1
    What is actually important is that if you do `a.x = 1001`, that will not affect `b.x`. – zvone Dec 21 '20 at 16:14
  • The interpreter isn't necessarily going to do the same deduping trick for any arbitrary instance where a variable is set to the value `1000`. I suspect it's easy in this case because it's the same actual line of code. Note that stuff like this is an *implementation detail* of the language and is not something you should depend on to always work the same way! – Samwise Dec 21 '20 at 16:16
  • @satindersingh zvone's comment is the correct explanation of what's happening; if you tested `x = 1000` and `y = 1000` and found they have different IDs, the reason is because you tested this in interactive mode, on two different lines. Constants are only deduplicated if they are within the same code object (i.e. the same file, or the same line when entered in interactive mode). – kaya3 Dec 21 '20 at 16:17
  • @kaya3 I came from c++ background, and was confusing things with that. The discussion has solved my queries. Thank you. – satinder singh Dec 21 '20 at 16:22

1 Answers1

2

Inheritance has nothing to do with this.

class Thing:
    def __init__(self):
        self.x = 1000

    def __str__(self):
        return f"{self.x} {id(self.x)}"


thing1 = Thing()
thing2 = Thing()
print(id(thing1), thing1)
print(id(thing2), thing2)

prints:

2469313072288 1000 2469313145456
2469312951344 1000 2469313145456

When the line self.x = 1000 is executed, it assigns self.x to the same immutable object -- an int of value 1000 whose id is 2469313145456. No subclassing is necessary to demonstrate this.

Note that the two Thing instances themselves have different ids.

Samwise
  • 68,105
  • 3
  • 30
  • 44
  • 2
    Nice. I think the OP is confusing the `id(a.x)` with the C++ `&(a.x)`, which is not the same, because in C++ `a.x = 1` overwrites the data on that address, whereas in Python it changes the address at which `a.x` points. Therefore, it is not relevant whether two integers share the same `id` or not. – zvone Dec 21 '20 at 16:16