【问题标题】:Method inheritance issue方法继承问题
【发布时间】:2016-08-07 09:02:05
【问题描述】:

当我尝试创建一个“BJ_player”对象时:

player = BJ_player(name, number_chips)

我收到:

TypeError: init() 正好采用 2 个位置参数(给定 3 个)。

我使用从“BJ_Hand”继承的方法与从“Hand”继承的方法相同。

谁能解释一下?

第一个类位于'cardsmodule'中:

class Hand(object):
    """A hand of playing cards"""
    def __init__(self):
        self.cards = []

    def __str__(self):
        if self.cards:
            rep = ""
            for card in self.cards:
                rep += str(card) + "\t"
        else:
            rep = "<empty>"
        return rep
class BJ_hand(cardsmodule.Hand):
    """A BlackJack hand"""

    def __init__(self, name):
        super(BJ_hand, self).__init__()
        self.name = name

    def __str__(self):
        rep = self.name + "\t" + super(BJ_hand,self).__str__()
        if self.total:
            rep += "(" + str(self.total) + ")"
        return rep

class BJ_player(BJ_hand):
    """A BlackJack player"""
    def __init__(self, number_chips):
        super(BJ_player, self).__init__()
        #self.name = name
        self.number_chips = number_chips

    def __str__(self):
        rep = self.name + " has " + str(self.number_chips) + " chips.\n"
        rep += super(BJ_player, self).__init__()

【问题讨论】:

  • 您的BJ_player 类构造函数不需要name 参数。您需要添加一个name 参数并将其传递给super(BJ_player, self).__init__(name)
  • 这不是一个真正的多重继承问题,尽管有标题和标签。多重继承是指子类具有多个直接父类(例如母亲和父亲),而不是当您从一个本身继承自另一个类(例如父亲和祖父)的类继承时。

标签: python class inheritance methods


【解决方案1】:

您定义了一个 __init__ 方法,它只接受 一个 参数(加上 self):

class BJ_player(BJ_hand):
    """A BlackJack player"""
    def __init__(self, number_chips):
        #              ^^^^^^^^^^^^

name 没有参数,但您正在尝试将其传递:

player = BJ_player(name, number_chips)
#                  ^^^^  ^^^^^^^^^^^^

Python 不会为您寻找所有基本的 __init__ 方法;它只会“看到”BJ_player。如果您想为BJ_hand.__init__ 传递name 值,那么BJ_player.__init__() 必须 接受它作为参数。然后您可以通过super().__init__() 调用传递它:

class BJ_player(BJ_hand):
    """A BlackJack player"""
    def __init__(self, name, number_chips):
        super(BJ_player, self).__init__(name)

注意方法中的name 参数现在是如何在链中传递的。

【讨论】:

    【解决方案2】:

    这在 py2.7 和 py3.5 上没有错误:

    class Hand(object):
        """A hand of playing cards"""
        def __init__(self):
            self.cards = []
    
        def __str__(self):
            if self.cards:
                rep = ""
                for card in self.cards:
                    rep += str(card) + "\t"
            else:
                rep = "<empty>"
            return rep
    
    class BJ_hand(Hand):
        """A BlackJack hand"""
    
        def __init__(self, name):
            super(BJ_hand, self).__init__()
            self.name = name
    
    
        def __str__(self):
            rep = self.name + "\t" + super(BJ_hand,self).__str__()
            if self.total:
                rep += "(" + str(self.total) + ")"
            return rep
    
    class BJ_player(BJ_hand):
        """A BlackJack player"""
        def __init__(self, number_chips):
            super(BJ_player, self).__init__('aName')
            self.number_chips = number_chips
    
        def __str__(self):
            rep = self.name + " has " + str(self.number_chips) + " chips.\n"
            rep += super(BJ_player, self).__init__()
    
    b = BJ_player (3)
    

    【讨论】:

    • 该代码有效。但是当我开始我的二十一点游戏时,我需要向 BJ_player 传递一个名称和筹码数量,即 player = BJ_player(name, number_chips)。这会引发同样的错误。我缺少一些东西。
    【解决方案3】:

    BJ_player 类有问题。将类修改为:

    class BJ_player(BJ_hand):
        """A BlackJack player"""
        def __init__(self, name, number_chips):
            super(BJ_player, self).__init__(name)
            self.name = name
            self.number_chips = number_chips
    
        def __str__(self):
            rep = self.name + " has " + str(self.number_chips) + " chips.\n"
            rep += super(BJ_player, self).__init__(self.name)
    

    试过了,效果很好

    【讨论】:

      【解决方案4】:

      虽然其他答案(大部分)正确诊断了您所描述的具体问题(不接受 BJ_player.__init__ 中的 name 并在 super 调用中传递它),但我认为可能存在更大的设计问题在处理您的课程时给您带来其他问题。

      具体来说,玩家与其手中的牌之间的关系并不能很好地用继承来表示。继承通常被描述为“IS-A”关系。例如,定义一个继承自 Animal 父类的 Dog 类是有意义的,因为每只狗都是动物。

      这不是玩家和手的情况。二十一点玩家不是某种牌。每个玩家都有一手牌。对象之间的“HAS-A”关系最好通过组合来实现。也就是说,BJ_player 实例应该有一个Hand 实例作为实例变量。这可能会以其他方式释放您的设计。例如,当赌场不忙时,一个玩家可以在同一张桌子上同时玩几手牌。这不可能用继承来表示,但是将保存在Player 实例上的实例变量中的单个Hand 实例更改为一个或多个Hand 实例的列表是相当容易的。

      我还建议您存储在BJ_hand 上的name 属性确实更适合作为播放器的属性。拥有一个BJ_hand 类可能仍然有意义,它可以处理诸如计算发牌价值之类的事情(以及你是否已经破牌),但你可能需要考虑一下哪些属性会产生感觉可以放在手上,其他地方更合适。

      【讨论】:

      • 非常感谢。该设计直接来自我的初学者书籍。然而,我明白你的意思了,现在你让我想起了“有,是”的关系。我会按照你的描述制作一个版本。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-10
      • 2011-04-08
      • 2014-06-18
      • 2020-01-15
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      相关资源
      最近更新 更多