在 __init__ 内调用 @classmethod

calling a @classmethod within __init__

所以我尝试采用 OOP 方法来制作一副纸牌,它将由一张纸牌 class 和一副纸牌 class 组成。

我有一个 .csv 文件,其中包含每张牌(52 张牌)的 2 列(花色和点数)。

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

这里是 Card Class 的简单版本,用于在 Deck Class.

中创建卡片的每个实例
class Card:

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

对于我的套牌 class 的 __init__ 部分,我有几个循环可以打开 .csv 文件并将每个实例附加到空列表 self.cards Deck Class.

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)

如果您要从现有实例的 __init__ 方法中调用 create_deck 方法,那么将其作为 class 方法是没有意义的。将它作为一个常规的、未修饰的实例会更有意义,以 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方法很有用。它是你称之为 而不是 的东西 class 本身,它会为你创建实例:

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 文件加载的卡片创建一个牌组。