Vader
Vader

Reputation: 6716

Use class A method in class B, where B overwrites this method

I am aware of this question. Mine is similar, but not the same, because I overwrite said method. And I cannot use @staticmethod because I will need to use it on self as well in other functions of the class.

I have class Player and class Dealer. In Player I define a method called print_cards. In class Dealer I overwrite this method. How can I get a Dealer instance to use the Player's print_cards method and not its own?

class Player():
    def print_cards(self):
        print('I am in Player\'s class.')

class Dealer(Player):
    def print_cards(self):
        print('I am in Dealer\'s class.')

p = Player()
d = Dealer()

p.print_cards()
d.print_cards()

d.Player.print_cards()  # this is what I am thinking, but it is not valid python

>>> I am in Player's class.
>>> I am in Dealer's class.

Upvotes: 0

Views: 108

Answers (3)

Often one says that a method in superclass can be called with super().method(self), which is not quite the whole truth.

The super is often not the correct thing to do, in that it does not call the method in superclass, but the method that is in the next type in the current object's types method resolution order. In case of multiple inheritance it can call a method in a class that you did not anticipate:

class A(object):
    def say(self):
        print("I am A, just sayin'")

class B(A):
    def say(self):
        print("This is B, I let A speak for me")
        super().say()

B.say() calls A.say(), right?

Wrong, because we have also:

class C(A):
    def say(self):
        print("Hey it is me C")

class D(B, C):
    pass

Now we create an instance of D, and invoke say() on it:

D().say()

The output is:

This is B, I let A speak for me
Hey it is me C

That is, super() delegated the execution from B.say to the class C that the B is not aware at all, and B is neither a subclass nor superclass of C. The super() is a misnomer; it should really be called next_type or something. Thus in case you know what class to deliver to, do not use super but call the method explicitly:

class B(A):
    def say(self):
        print("This is B, I let A speak for me")
        A.say(self)

Upvotes: 1

ljetibo
ljetibo

Reputation: 3094

You mean something like this? Without super() you don't exactly override the parent method, just redefine it. (Not sure though, I try to avoid inheritance if I can).

class Player():
    def print_cards(self):
        print('I am in Player\'s class.')

class Dealer(Player):
    def print_cards(self):
        print('I am in Dealer\'s class.')
    def print_player(self):
        super().print_cards()

p = Player()
d = Dealer()

p.print_cards()
d.print_cards()
d.print_player()

Output is:

I am in Player's class.
I am in Dealer's class.
I am in Player's class.

Although specified as a Python 3 question, here's how you do it in Python 2

class Player(object):
    def print_cards(self):
        print('I am in Player\'s class.')

class Dealer(Player):
    def print_cards(self):
        print('I am in Dealer\'s class.')
    def print_player(self):
        super(Dealer, self).print_cards()

super works in different ways for python 2 and 3. Specifically notice the difference in def statement of Player class:

 class Player(object):

which is known as a "new-style" class in Python2. By default all classes in Python 3 are new-style classes if I remember correctly. Additionally notice that super requires a type of class of which you're looking for a parent, and an self which is an bound object, a child of the parent class.

Upvotes: 3

user4237459
user4237459

Reputation:

You can call a class's instance method with another self. E.g.:

class Player():
    def print_cards(self):
        print('I am in Player\'s class.')

class Dealer(Player):
    def print_cards(self):
        print('I am in Dealer\'s class.')

p = Player()
d = Dealer()

p.print_cards()
d.print_cards()

Player.print_cards(d)  # Not an instance

Output:

I am in Player's class
I am in Dealer's class
I am in Player's class

This is not very useful in this circumstance. Another example:

class Being:
    def __init__(self):
        self.saying = "Patience is a virtue."
        self.home = "Earth"

    def say_virtue(self):
        print(self.saying)

    def say_home(self):
        print(self.home)

class Yoda:
    def __init__(self):
        self.saying = "Is patience virtue a."
        self.home = "Far galaxy away far."

    def say_virtue(self):
        print("Mean you 'Virtue say'?")

yoda = Yoda()
being = Being()

being.say_virtue()  # Says beings virtue
yoda.say_virtue()   # Says yodas virtue
Being.say_virtue(yoda)   # says Beings virtue with yodas `self.virtue`
# And as a side note:
print(yoda.say_home == being.say_home)  # Instances
print(Yoda.say_home == Being.say_home)  # Classes

## Prints:
Patience is a virtue.
Mean you 'Virtue say'?
Is patience virtue a.
False
True

Upvotes: 1

Related Questions