python - 作用于另一个类的多个实例的类函数
问题描述
我正在使用类构建一个简单的纸牌游戏,但遇到了一些令人困惑的事情。
首先是我的“Deck”类的相关方法。
class Deck(object):
def __init__(self, starting_cards=[]):
self._cards = starting_cards
def get_amount(self):
return len(self._cards)
def add_card(self, card):
self._cards.append(card)
这是我的“玩家”课程的一部分:
class Player(object):
def __init__(self, name):
self._name = name
self._hand = Deck()
self._coders = Deck()
def get_hand(self):
return self._hand
def get_coders(self):
return self._coders
def has_won(self):
if self._coders.get_amount() >= 4:
return True
else:
return False
有一些“卡片”子类,但它们与这个问题无关,下面的代码应该向 self._hand 添加 3 张卡片,但它将卡片添加到 self._hand 和 self._coders,这是两个完全不同的Deck() 类的实例。
player = Player("Lochie Deakin-Sharpe")
player.get_hand().add_card(NumberCard(3))
player.get_hand().add_card(KeyboardKidnapperCard())
player.get_hand().add_card(AllNighterCard())
player.get_hand()
我的代码的哪一部分将这些卡片添加到 self._coders 中,据我所知没有调用?
运行上面的代码后,这里有一些命令:
>>> player.get_coders()
Deck(NumberCard(3), KeyboardKidnapperCard(), AllNighterCard())
>>> player.get_hand().add_card(4)
>>> player.get_hand()
Deck(NumberCard(3), KeyboardKidnapperCard(), AllNighterCard(), 4)
>>> player.get_coders()
Deck(NumberCard(3), KeyboardKidnapperCard(), AllNighterCard(), 4)
解决方案
看起来您的 Player 类有两个相同 _cards 列表的引用。
在 Python 中,您必须非常小心地将列表作为默认参数传递。要了解我的意思,请在定义类后运行以下代码:
p = Player('Me')
print('Memory Address of Hand: 0x{}'.format(id(p.get_hand()._cards)))
print('Memory Address of Coders: 0x{}'.format(id(p.get_coders()._cards)))
注意hand list和coder list的内存地址是一样的。这是因为将默认列表从参数直接传递到类属性的棘手行为。
要避免这种行为,请将以下位添加到您的 Deck初始化函数中:
def __init__(self, starting_cards=None):
if starting_cards is None:
starting_cards = []
self._cards = starting_cards
我们将把starting_cards 设置为None,而不是直接从默认参数传递空列表。如果我们发现未传递起始卡片列表,则实例化一个空列表,然后将其分配给 _cards 属性。通过这样做,您可以避免对同一数组指针的多次引用。
这是一个常见的 Python 问题。如果您有兴趣了解更多关于它的信息,这篇文章很好地触及了这个概念:https ://docs.python-guide.org/writing/gotchas/
此外,Raymond Hettinger 就 Python 类开发的细微差别做了精彩的演讲。该视频来自 2013 年,但它仍然涵盖了在 Python 3 中制作 Pythonic 类所需的许多概念:https ://www.youtube.com/watch?v=HTLu2DFOdTg
例如,最好@property
在 Python 类中使用而不是显式的 getter 和 setter,这有助于随着时间的推移提高类的性能和可读性。
推荐阅读
- javascript - D3 - 批量可视化节点(避免链接交叉)
- python - 将基于 Django 模型表单的系统转换为基于原始 HTML 的表单系统以进行注册
- javascript - 在 JS 中,为什么我可以使用诸如 toFixed() 之类的函数,它驻留在原始类型的 Number 包装器对象的原型中?
- javascript - 为什么我不能在状态中存储对象数组:React JS
- woocommerce - woocommerce结帐自定义字段更新订单元
- python - 没有名为“sqlalchemy”的模块
- kubernetes - 我怎么知道为什么我的 SonarQube helm chart 会被 Kubernetes 自动杀死
- python-3.x - 类中未定义的函数
- php - Mysql,获取两个日期之间的数据,如果开始日期没有数据,我需要从最后输入的日期获取数据吗?
- bootstrap-4 - 我可以防止 Bootsrap 覆盖表格中的链接颜色吗?