You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MTG卡牌集管理程序开发疑问:对象创建与存储方案咨询

解答你的万智牌集管理程序问题

先直接回应你的两个核心问题:

问题一:不同卡组的同名卡牌实例会被覆盖吗?

不会。你每次调用Card()创建的都是一个独立的对象,哪怕两张卡牌名字相同,它们在内存中是完全分开的实例,各自属于对应的CardSet对象,互相之间不会产生覆盖。不过要注意你当前代码里的add_card方法有问题,会导致卡牌无法被持久存储(后面会详细说)。

问题二:用字典列表存储卡牌是不是更简便合理?

这取决于你的程序需求:

  • 如果只是简单存储和读取卡牌数据,用字典列表确实更轻便,代码量更少,不需要定义Card类。比如每张卡牌用{"card_name": "xxx", "amount": 1, ...}这样的字典表示,直接存在CardSet的列表里。
  • 但如果你的程序后续需要扩展功能(比如给卡牌添加计算方法、验证属性合法性、统一处理闪卡/签名逻辑等),用Card类的面向对象方式会更合理——它能提供类型约束,避免属性拼写错误,也更容易维护和扩展。

你的当前代码存在的几个关键问题

我帮你梳理下代码里的bug,这些问题会导致你的卡牌集无法正常工作:

  1. CardSet.add_card方法缺少self参数:作为类的实例方法,必须把self作为第一个参数,否则无法访问实例的属性。
  2. add_card里的cards是局部变量:每次调用add_card都会新建一个空列表,添加完卡牌后返回,但这个列表没有和CardSet实例绑定,导致之前添加的卡牌全部丢失。应该把cards作为CardSet的实例属性,在__init__里初始化。
  3. CSV处理时的逻辑错误:你把row[3]直接赋值为CardSet对象,之后循环里再判断row[3] not in list_sets就会出错(因为list_sets存的是字符串,而row[3]现在是对象)。应该先提取集合名称字符串,再进行判断。
  4. 没有处理表头和数据类型转换:CSV文件第一行通常是表头,需要跳过;另外amountnumb_foil是数字,signed是布尔值,直接读取的字符串需要转换类型。

改进后的代码示例

下面是修正后的代码,解决了上面的问题:

import csv

class CardSet:
    def __init__(self, set_name):
        self.set_name = set_name
        self.cards = []  # 用实例属性存储卡牌,持久化保存
    
    def get_set(self):
        return self.set_name
    
    def add_card(self, card_name, card_num, amount, numb_foil, signed):
        # 创建Card实例并添加到当前卡组的卡牌列表中
        card = Card(card_name, card_num, int(amount), int(numb_foil), signed.lower() == 'yes')
        self.cards.append(card)

class Card:
    def __init__(self, card_name, card_num, amount, numb_foil, signed):
        self.card_name = card_name
        self.card_num = card_num
        self.amount = amount
        self.numb_foil = numb_foil
        self.signed = signed

def csv_reader():
    set_objects = {}  # 用字典存储卡组,键为卡组名称,值为卡组对象,查找更高效
    
    with open('Collection.csv', 'rt', encoding='utf8') as f:
        cards = csv.reader(f)
        next(cards)  # 跳过CSV表头
        
        for row in cards:
            # 提取各字段,确保索引正确(根据你的注释对应)
            amount_owned = row[0]
            card_name = row[2]
            set_name = row[3]
            card_num = row[4]
            foil_owned = row[6]
            signed = row[7]
            
            # 检查卡组是否已存在
            if set_name not in set_objects:
                # 创建新卡组对象
                new_set = CardSet(set_name)
                set_objects[set_name] = new_set
                # 添加当前卡牌到新卡组
                new_set.add_card(card_name, card_num, amount_owned, foil_owned, signed)
            else:
                # 找到已存在的卡组,添加卡牌
                set_objects[set_name].add_card(card_name, card_num, amount_owned, foil_owned, signed)

csv_reader()

额外建议

  • 可以给CardSet添加查找卡牌的方法,比如根据卡牌名称或编号快速查找,避免每次都遍历列表。
  • 如果需要统计卡组内的卡牌总数、闪卡占比等,直接在CardSet类里添加对应的方法即可,面向对象的优势在这里会体现得很明显。

内容的提问来源于stack exchange,提问作者pyRN

火山引擎 最新活动