-1

I've wrote the following code to explain what I've found using super(). :

With Parent.set_prop():

class Parent:
    parent_prop = None

    @classmethod
    def set_prop(cls, value):
        cls.parent_prop = value


class Child1(Parent):
    @classmethod
    def set_prop(cls, value):
        print("Child1 set parent prop")
        Parent.set_prop(value)


class Child2(Parent):
    pass


cls1 = Child1()
cls2 = Child2()
cls1.set_prop(10)

print(cls1.parent_prop)
print(cls2.parent_prop)

With super().set_prop()

class Parent:
    parent_prop = None

    @classmethod
    def set_prop(cls, value):
        cls.parent_prop = value


class Child1(Parent):
    @classmethod
    def set_prop(cls, value):
        print("Child1 set parent prop")
        super().set_prop(value)


class Child2(Parent):
    pass


cls1 = Child1()
cls2 = Child2()
cls1.set_prop(10)

print(cls1.parent_prop)
print(cls2.parent_prop)

The result of the first execution is:

Child1 set parent prop
10
10

The result of the second execution is:

Child1 set parent prop
10
None

I didn't expect any differences between both. Why calling the set_prop method with super() doesn't set the value for all instances of the class?

Jordan Russev
  • 57
  • 1
  • 3
  • 2
    Can you show the actual code instead of the vague description *"If the Base.setUpClass() in test class 1 is replaced with super().setUpClass()"*? – deceze Feb 07 '22 at 10:00
  • "The result of the execution is" Result of executing *what*? The code only defines classes, it never actually instantiates them or calls their methods. – MisterMiyagi Feb 07 '22 at 10:04
  • FWIW, filling in some blanks I *think* the issue is that ``cls`` differs when the classmethod is called on ``super()`` vs ``Base`` – which is somewhat to be expected but admittedly not exactly obvious. If that is the case, you might want to seriously cut down the example – a ``classmethod`` that just ``print(cls)`` and two child classes calling the classmethod via ``__init__`` should suffice. – MisterMiyagi Feb 07 '22 at 10:06
  • @MisterMiyagi - first of all the example is with unittest and if you use it as a runner that will be the result. For the second comment - may be this is the case , but can you explain that behavior in details? – Jordan Russev Feb 07 '22 at 13:04
  • I've updated the example. I hope it's a way clear now. – Jordan Russev Feb 07 '22 at 13:12

1 Answers1

2

The difference is obvious when you add a print(cls) to Parent.set_prop :

    @classmethod
    def set_prop(cls, value):
        print(cls)
        cls.parent_prop = value

When ran in case 1 :

Child1 set parent prop
<class '__main__.Parent'>
10
10

When ran in case 2 :

Child1 set parent prop
<class '__main__.Child1'>
10
None

That's because super does not give you the parent class, but a proxy which will call the parent's methods (using a special __getitem__) but with the same parameters, here the same value for cls which is Child1 in the second case, but simply Parent in the first case.

Lenormju
  • 4,078
  • 2
  • 8
  • 22