【问题标题】:Use class A method in class B, where B overwrites this method在 B 类中使用 A 类方法,其中 B 覆盖此方法
【发布时间】:2015-02-21 16:09:14
【问题描述】:

我知道这一点question。我的类似,但不一样,因为我覆盖了所说的方法。我不能使用@staticmethod,因为我需要在self 以及该类的其他函数中使用它。

我有class Playerclass Dealer。在Player 中,我定义了一个名为print_cards 的方法。在课堂Dealer 我覆盖了这个方法。如何让 Dealer 实例使用 Playerprint_cards 方法而不是它自己的方法?

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.

【问题讨论】:

  • 试试Player.print_cards(d)

标签: python oop python-3.x


【解决方案1】:

你的意思是这样的?如果没有 super(),您不会完全覆盖父方法,只需重新定义它。 (虽然不确定,如果可以的话,我会尽量避免继承)。

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()

输出是:

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

虽然指定为 Python 3 问题,但在 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 在 python 2 和 3 中的工作方式不同。特别注意 Player 类的 def 语句的区别:

 class Player(object):

在 Python2 中被称为“新式”类。如果我没记错的话,默认情况下,Python 3 中的所有类都是新型类。另外请注意,super 需要一个您正在寻找其父类的类类型,以及一个作为绑定对象的 self,它是父类的子类。

【讨论】:

  • 您应该在此处突出显示 Python 2/3 的差异。
  • @Mr.F 问题指定了 Python3。我已经添加了差异,这是正确的吗? (就像我说的,我尽量避免继承)
  • 如果Player.print_cards() 导入的不仅仅是self,我是否必须在我的Super.print_cards() 中指定它们?
  • @Vader 如果导入是指参数,那么当然可以。它的行为与您在那里有一个 instance.method(args/kwargs) 完全相同。
【解决方案2】:

你可以用另一个self调用一个类的实例方法。例如:

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

输出:

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

这在这种情况下不是很有用。另一个例子:

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

【讨论】:

  • 我将使用Player.print_cards(d),因为我只需要这样做一次。谢谢。
【解决方案3】:

经常有人说超类中的方法可以用super().method(self) 调用,这并不完全是事实。

super 通常不是正确的做法,因为它不调用超类中的方法,而是在当前对象的类型方法解析顺序中的下一个类型中的方法。 em> 在多重继承的情况下,它可以调用一个你没有预料到的类中的方法:

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() 打电话给A.say(),对吧?

错了,因为我们也有:

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

class D(B, C):
    pass

现在我们创建一个D 的实例,并在其上调用say()

D().say()

输出是:

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

也就是说,super()B.say 的执行委托给了 B 根本不知道的类 C,并且 B 既不是 C 的子类也不是超类。 super() 用词不当;它真的应该叫next_type 什么的。因此,如果您知道要传递给哪个类,请不要使用super,而是显式调用该方法:

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

【讨论】: