【问题标题】:calling a @classmethod within __init__在 __init__ 中调用 @classmethod
【发布时间】:2021-12-29 03:02:26
【问题描述】:

所以我尝试采用 OOP 方法来制作一副由卡片类和卡片组类组成的卡片组。

我有一个 .csv 文件,其中包含每张卡片(52 张卡片)的 2 列(花色和等级)。

suit,rank
Spades,2
Spades,3
Spades,4...

这是Card 类的简单版本,用于在Deck 类中创建卡片的每个实例。

class Card:

    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank
        self.name = f"{self.rank} of {self.suit}"

对于我的甲板类的__init__ 部分,我有几个循环打开.csv 文件并将每个实例附加到Deck 类的空列表self.cards 中。

import csv
from cards import Card

cards_csv = "C/:path...."

class Deck:
    def __init__(self):
        self.cards = []
        with open(cards_csv, "r") as f:
            reader = csv.DictReader(f)
            deck = list(reader)

        for card in deck:
            card = Card(
                suit=str(card.get("suit")),
                rank=str(card.get("rank"))
            )
            self.cards.append(card.name)

我想知道它是否更优化,以及是否有办法将这些循环分配到 @classmethod。我知道@classmethod 会调用__init__,但是否可以反过来呢?即

class Deck:
    def __init__(self):
        self.cards = []
        self.create_deck()

    @classmethod
    def create_deck(cls):
        with open(cards_csv, "r") as f:
            reader = csv.DictReader(f)
            deck = list(reader)

        for card in deck:
            card = Card(
                suit=str(card.get("suit")),
                rank=str(card.get("rank"))
            )
            cls.append(card.name)

【问题讨论】:

    标签: python-3.x oop inheritance class-method load-csv


    【解决方案1】:

    如果你要从一个已经存在的实例的__init__ 方法调用create_deck 作为一个类方法是没有意义的。将self 作为参数,让它成为一个常规的、未修饰的实例会更有意义:

    def create_deck(self):
        with open(cards_csv, "r") as f:
            reader = csv.DictReader(f)
            deck = list(reader)
    
        for card in deck:
            card = Card(
                suit=str(card.get("suit")),
                rank=str(card.get("rank"))
            )
            self.cards.append(card.name)
    

    如果你想要一个替代的构造函数,类方法很有用。它是你调用的东西而不是类本身,它会为你创建实例:

    class Deck:
        def __init__(self):
            self.cards = []
            # don't call create_deck here, it's now an optional alternative constructor
    
        @classmethod
        def create_deck(cls):
            with open(cards_csv, "r") as f:
                reader = csv.DictReader(f)
                deck = list(reader)
    
            inst = cls()                      # create the instance
    
            for card in deck:
                card = Card(
                    suit=str(card.get("suit")),
                    rank=str(card.get("rank"))
                )
                inst.cards.append(card.name)  # append to the new instance's cards list
    
            return inst
    

    现在您可以使用Deck() 创建一个空牌组,或者使用Deck.create_deck() 从CSV 文件加载的牌创建一个。

    【讨论】:

    • 谢谢!我最初将它作为一个普通的未装饰实例。但是我想以某种方式合并@classmethod,但没有得出您上面所说的解决方案。
    • 我尝试使用替代构造方法,但是当我尝试使用Deck.create_deck() 时,它返回None
    • create_deck() 没有返回语句
    • @LaidBackLuck:哎呀,对不起。正如 Pablo 指出的那样,我忘记了最后的 return 声明。
    • @Blckknght 和 Pablo 一切都好!睡了一会儿,回到这些 cmets 后,我不敢相信答案如此简单。我的失望是无法估量的,但我的一天并没有被毁掉。谢谢你们!
    猜你喜欢
    • 2019-11-08
    • 2013-02-23
    • 2023-04-10
    • 2018-04-15
    • 1970-01-01
    • 2021-08-14
    • 2021-05-19
    • 2012-09-20
    相关资源
    最近更新 更多