微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

定义为另一个列表类型类属性长度的类属性不会自行更新并始终返回相同的值

如何解决定义为另一个列表类型类属性长度的类属性不会自行更新并始终返回相同的值

我正在为纸牌游戏“战争”编写代码。在定义“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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?