如何解决定义为另一个列表类型类属性长度的类属性不会自行更新并始终返回相同的值
我正在为纸牌游戏“战争”编写代码。在定义“Deck”类时,我定义了一个属性“self.cards”,它给出了一副牌中当前所有牌的列表。我还定义了一个属性“self.length”,它应该给出“self.cards”属性的长度。
但是,当我使用表达式 deck.length
时,它返回一个固定值,即使卡片组中的卡片(“self.cards”)被移除也不会改变/添加。另一方面,当我使用表达式 len(deck.cards)
时,它返回所需的输出(即更新后的牌组大小)。
代码是:
# I've used only two suits and three ranks to explain this problem
suits = ('Hearts','Spades')
ranks = ('Queen','King','Ace')
class Card():
def __init__(self,suit,rank):
self.suit = suit
self.rank = rank
class Deck():
def __init__(self):
# Create an empty deck and fill it with the available cards
self.cards = []
for suit in suits:
for rank in ranks:
self.cards.append(Card(suit,rank))
self.length = len(self.cards)
def deal_top_card (self):
self.cards.pop(0)
deck = Deck()
# Removing Three cards one after the other
deck.deal_top_card()
deck.deal_top_card()
deck.deal_top_card()
print(f"Length according to length attribute = {deck.length}")
print(f"Length of the list of cards = {len(deck.cards)}")
Length according to length attribute = 6
Length of the list of cards = 3
解决方法
您的问题是 length
只是一个属性。这意味着它在定义时接收一个值,并保持该值直到再次赋值。
但是 Python 有一个概念,可以用属性来做你想做的事:
class Deck():
def __init__(self):
# Create an empty deck and fill it with the available cards
self.cards = []
for suit in suits:
for rank in ranks:
self.cards.append(Card(suit,rank))
@property
def length(self):
return len(self.cards)
def deal_top_card (self):
self.cards.pop(0)
属性用作特殊成员,每次使用时都会实际执行方法。您现在可以成功使用:
deck = Deck()
# Removing Three cards one after the other
deck.deal_top_card()
deck.deal_top_card()
deck.deal_top_card()
print(f"Length according to length attribute = {deck.length}")
print(f"Length of the list of cards = {len(deck.cards)}")
并按预期获得:
Length according to length attribute = 3
Length of the list of cards = 3
顺便说一句,属性更强大,并且可以在分配或删除时调用其他方法。阅读https://docs.python.org/3/library/functions.html#property了解更多...
,您只是在 init() 方法中更新 self.length。因此,它不会在您每次弹出卡片时自行更新。 Init 仅在创建对象时调用一次。你应该添加这个:
def deal_top_card (self):
self.cards.pop(0)
self.length = len(self.cards)
每次弹出卡片时更新长度
,At 属性不会自行更新。看起来您想要一个属性或一个方法。
如果您想像访问属性一样访问 length
,则属性是您想要使用的东西。如果某些代码想要覆盖长度值,它还可以让您控制发生的情况:
class Deck:
....
@property
def length(self):
return len(self.cards)
...
print(f"Length according to length property = {deck.length}")
一个方法类似,但你明确调用它:
class Deck:
....
def length(self):
return len(self.cards)
...
print(f"Length according to length method = {deck.length()}")
最后,您可以定义魔法 __len__
并调用 len(deck)
,因为长度的概念适用于 Python 中的许多类型。
此外,您可能会认为 Deck
是一个与“卡片序列”非常相似的概念,因此将其作为 list
的子类可能是有意义的,在这种情况下,您不会根本不需要定义长度方法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。