我正在为纸牌游戏"War"编写代码。在定义";甲板";类,我定义了一个属性";self.cards";其给出当前在一副牌中的所有牌的列表。我还定义了一个属性";自身长度";预计这将给出"0"的长度;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
的子类可能是有意义的,在这种情况下,您根本不需要定义length方法。