You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现塔罗牌正逆位功能时如何解决卡片存在性判断失效问题

塔罗牌卡组实现问题解决方案

问题根因

Python 中in运算符对自定义序列类的默认判断逻辑是遍历所有元素,逐个与目标值做相等校验。你当前实现的__getitem__方法返回的是(Card实例, 方向字符串)二元组,因此in运算符会默认拿你传入的Card对象和二元组对比,自然返回False,只有刚好匹配对应方向的二元组才会返回True。

解决方案

最简便的实现是给FrenchTarot类新增__contains__方法,该方法会被in运算符优先调用,无需修改现有抽卡逻辑即可同时满足两个需求:

  • 用下标取卡(即抽卡)时仍返回带随机正逆位的结果
  • 用in判断卡牌是否存在时仅校验卡牌本身,忽略方向

修改后的完整代码如下:

import collections
from random import getrandbits

Card = collections.namedtuple('Card', ['rank','suit'])

class FrenchTarot:
  ranks = [str(n) for n in range(1,11)]+['Page','Knight','Queen','King']
  suits = 'wands swords coins cups'.split()
  major_arcana = ['The Fool', 'The Magician', 'The High Priestess', 'The Empress',
                  'The Hierophant', 'The Lovers', 'The Chariot', 'Strength',
                  'The Hermit', 'Wheel of Fortune', 'Justice', 'The Hanged Man',
                  'Death', 'Temperance', 'The Devil', 'The Tower', 'The Star',
                  'The Moon', 'The Sun', 'Judgement', 'The World']

  def __init__(self):
    self.minor = [Card(rank, suit) for suit in self.suits for rank in self.ranks]
    self.major = [Card(rank, 'Major Arcana') for rank in self.major_arcana]
    self._cards = self.major + self.minor

  def __len__(self):
    return len(self._cards)

  def __repr__(self):
    return f'Tarot Deck containing {len(self)} cards, {len(self.major)} Major Arcana, and {len(self.minor)} Minor Arcana'

  def __getitem__(self,position):
    if getrandbits(1):
      orientation = 'Upright'
    else:
      orientation = 'Reversed'
    return self._cards[position], orientation

  def __setitem__(self, position, card):
    self._cards[position] = card
  
  # 新增方法,自定义in运算符判断逻辑
  def __contains__(self, item):
    # 支持单独查询卡牌是否存在
    if isinstance(item, Card):
        return item in self._cards
    # 也支持查询带方向的卡牌是否匹配
    elif isinstance(item, tuple) and len(item) == 2:
        target_card, target_orient = item
        return any(card == target_card and orient == target_orient for card, orient in self)
    return False

可选替代方案

如果你不想修改__contains__的默认逻辑,也可以把随机方向的逻辑从__getitem__中剥离,单独实现一个draw方法:

# 修改__getitem__返回纯Card对象,保证in逻辑正常
def __getitem__(self,position):
    return self._cards[position]

# 新增抽卡方法,返回带随机方向的卡牌
def draw(self, position):
    orientation = 'Upright' if getrandbits(1) else 'Reversed'
    return self[position], orientation

后续抽卡时调用deck.draw(下标)即可获取带方向的卡牌,in运算符也可以正常判断卡牌是否存在。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:24:05