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

Python扑克手牌比较程序__str__与__repr__方法实现求助

魔法方法实现方案

__str__ 面向普通用户,输出直观易读的展示内容;__repr__ 面向开发者,输出可直接执行、重建对应对象的表达式:

Card 类魔法方法

  • __str__:输出「牌面缩写+花色符号」,比如 A♥、10♤、3♦
  • __repr__:输出可直接实例化Card的表达式,比如 Card(suit='hearts', name='ace')
    实现代码:
def __str__(self):
    # 牌面名称转缩写
    name_abbr = {
        'ace': 'A', 'king': 'K', 'queen': 'Q', 'jack': 'J'
    }.get(self.name, self.name)
    return f"{name_abbr}{self.card_suits[self.suit]}"

def __repr__(self):
    return f"Card(suit={self.suit!r}, name={self.name!r})"

Hand 类魔法方法

  • __str__:输出所有牌的列表+当前手牌等级,比如 [10♤, J♤, Q♤, K♤, A♤] 皇家同花顺
  • __repr__:输出可直接实例化Hand的表达式
    实现代码:
def __str__(self):
    # 先获取手牌等级名称
    rank_map = [
        (self.royal_flush, "皇家同花顺"),
        (self.straight_flush, "同花顺"),
        (self.four_of_a_kind, "四条"),
        (self.full_house, "葫芦"),
        (self.flush, "同花"),
        (self.straight, "顺子"),
        (self.three_of_kind, "三条"),
        (self.two_pair, "两对"),
        (self.one_pair, "一对"),
        (lambda: True, "高牌")
    ]
    for check_func, rank_name in rank_map:
        if check_func():
            break
    return f"{[str(c) for c in self.cards]} {rank_name}"

def __repr__(self):
    return f"Hand(card_list={self.cards!r})"

代码优化建议
  • 给Card.__init__加非法参数校验:当前代码如果传入非法花色,不会给self.suit赋值,后续调用会抛出属性错误,建议非法参数直接抛出明确的ValueError
  • 用functools.total_ordering装饰器简化比较方法:只要实现__lt__和__eq__,其余大小比较方法会自动生成,无需手动编写__gt__
  • 弃用冗余的getter方法:Python不需要像Java一样编写get_value、get_suit这类方法,直接访问实例属性即可,代码更简洁
  • 优化顺子判断逻辑:当前代码不支持A-2-3-4-5这类最小顺子,可加特殊判断处理
  • 用collections.Counter优化牌数统计逻辑:当前_pair、_of_a_kind方法的实现效率低、可读性差,用Counter统计牌面出现次数会清晰很多
  • 优化手牌强度比较逻辑:当前determine_strength只加了基础分+高牌,同牌型下无法区分大小(比如两对A,A,K,K,2和A,A,Q,Q,J,按现有逻辑得分相同,实际前者更大),建议把得分拆成「基础分+牌组权重元组」比较,同牌型下按元组优先级比较

修改后完整可运行代码
import random
from functools import total_ordering
from collections import Counter

@total_ordering
class Card(object):
    card_values = {'ace' : 13, 'king' : 12, 'queen' : 11, 'jack' : 10,
                    '10' : 9, '9' : 8, '8' : 7, '7' : 6, '6' : 5,
                    '5' : 4, '4' : 3, '3' : 2, '2' : 1}
    card_suits = {'spades' : u'♤', 'diamonds' : u'♦', 'clubs': u'♧', 'hearts' : u'♥'}
    name_abbr = {'ace': 'A', 'king': 'K', 'queen': 'Q', 'jack': 'J'}
    
    def __init__(self, suit, name):
        if name not in self.card_values:
            raise ValueError(f"非法牌面,合法值为{list(self.card_values.keys())}")
        if suit not in self.card_suits:
            raise ValueError(f"非法花色,合法值为{list(self.card_suits.keys())}")
        self.name = name
        self.value = self.card_values[name]
        self.suit = suit

    def __lt__(self, other):
        return self.value < other.value

    def __eq__(self, other):
        return isinstance(other, Card) and (self.value == other.value) and (self.suit == other.suit)

    def __str__(self):
        abbr = self.name_abbr.get(self.name, self.name)
        return f"{abbr}{self.card_suits[self.suit]}"

    def __repr__(self):
        return f"Card(suit={self.suit!r}, name={self.name!r})"

    def same_suit(self, other):
        return self.suit == other.suit

class Hand(object):
    def __init__(self, card_list):
        assert len(card_list) == 5, "手牌必须为5张牌"
        self.cards = sorted(card_list)
        # 提前统计牌面出现次数,避免重复计算
        self.value_counts = Counter(c.value for c in self.cards)
        self.count_values = sorted(self.value_counts.values(), reverse=True)
        self.sorted_values = sorted(self.value_counts.keys(), reverse=True)

    def determine_strength(self):
        # 返回(基础分, 权重元组),直接比较元组大小即可判断手牌强弱
        if self.royal_flush():
            return (10, ())
        elif self.straight_flush():
            return (9, (self.sorted_values[0],))
        elif self.four_of_a_kind():
            four_val = next(k for k,v in self.value_counts.items() if v==4)
            kicker = next(k for k,v in self.value_counts.items() if v==1)
            return (8, (four_val, kicker))
        elif self.full_house():
            three_val = next(k for k,v in self.value_counts.items() if v==3)
            pair_val = next(k for k,v in self.value_counts.items() if v==2)
            return (7, (three_val, pair_val))
        elif self.flush():
            return (6, tuple(self.sorted_values))
        elif self.straight():
            return (5, (self.sorted_values[0],))
        elif self.three_of_kind():
            three_val = next(k for k,v in self.value_counts.items() if v==3)
            kickers = sorted([k for k,v in self.value_counts.items() if v==1], reverse=True)
            return (4, (three_val, *kickers))
        elif self.two_pair():
            pairs = sorted([k for k,v in self.value_counts.items() if v==2], reverse=True)
            kicker = next(k for k,v in self.value_counts.items() if v==1)
            return (3, (*pairs, kicker))
        elif self.one_pair():
            pair_val = next(k for k,v in self.value_counts.items() if v==2)
            kickers = sorted([k for k,v in self.value_counts.items() if v==1], reverse=True)
            return (2, (pair_val, *kickers))
        return (1, tuple(self.sorted_values))

    def flush(self):
        suit = self.cards[0].suit
        return all(c.suit == suit for c in self.cards)

    def straight(self):
        values = sorted(c.value for c in self.cards)
        # 普通顺子判断
        if values == list(range(values[0], values[0]+5)):
            return True
        # 特殊处理A-2-3-4-5顺子
        return values == [1,2,3,4,13]

    def straight_flush(self):
        return self.straight() and self.flush()

    def royal_flush(self):
        return self.straight_flush() and self.cards[-1].name == 'ace' and self.cards[0].value == 9

    def one_pair(self):
        return self.count_values[0] == 2

    def two_pair(self):
        return self.count_values[0] == 2 and self.count_values[1] == 2

    def three_of_kind(self):
        return self.count_values[0] == 3

    def four_of_a_kind(self):
        return self.count_values[0] == 4

    def full_house(self):
        return self.count_values[0] == 3 and self.count_values[1] == 2

    def __str__(self):
        rank_map = [
            (self.royal_flush, "皇家同花顺"),
            (self.straight_flush, "同花顺"),
            (self.four_of_a_kind, "四条"),
            (self.full_house, "葫芦"),
            (self.flush, "同花"),
            (self.straight, "顺子"),
            (self.three_of_kind, "三条"),
            (self.two_pair, "两对"),
            (self.one_pair, "一对"),
            (lambda: True, "高牌")
        ]
        for check_func, rank_name in rank_map:
            if check_func():
                break
        return f"{[str(c) for c in self.cards]} {rank_name}"

    def __repr__(self):
        return f"Hand(card_list={self.cards!r})"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 07:36:02