python child class method calling overridden classmethod with non-classmethod

Issue

I am trying to do the following in python3:

class Parent:
    @classmethod
    def show(cls, message):
        print(f'{message}')

    @classmethod
    def ask(cls, message):
        cls.show(f'{message}???')

class Child(Parent):
    @property
    def name(self):
        return 'John'

    def show(self, message):
        print(f'{self.name}: {message}')

instance = Child()
instance.ask('what')

But it then complains

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in ask
TypeError: Child.show() missing 1 required positional argument: 'message'

even so child.show works as expected. So it seems that child.ask is calling Parent.show… I tried to mark Child.show as classmethod too, but then the cls.name is not showing the expected output:

class Child2(Parent):
    @property
    def name(self):
        return 'John'

    @classmethod
    def show(cls, message):
        print(f'{cls.name}: {message}')

instance2 = Child2()
instance2.ask('what')

this shows

<property object at 0xfc7b90>: what???

Is there a way to override a parent classmethod with a non-classmethod, but keeping other parent classmethod to call the overridden one?

Solution

I found it hard to follow for the second half of the question but there was an issue I saw and it might help you solve your problem.

When you said even so child.show works as expected. So it seems that child.ask is calling Parent.show, thats not what is happening.

When you called instance.ask("what"), it called the @classmethod decorated method of the Child class (which is inherited from the parent). This ask method is passing the class Child as the first argument, (not the instance you created). This means the line

cls.show(f'{message}???')

is equivalent to

Child.show(f'{message}???') # because cls is the Class not the instance

The show method inside the Child class is an instance method and expects the first argument to be the actual instance (self) but the string f'{message}???' is being passed to it and it expects a second message string to be passed so that’s why its is throwing an error.

Hope this helped

Answered By – Elias Amha

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published