Python:'列表中的对象'检查和'__cmp__'溢出

Ulq*_*aru 16 python list object cmp playing-cards

这是我第一次出现堆栈溢出,所以如果格式不适合该网站,我很抱歉.我刚刚开始学习编程,差不多已经过去了2周.我正在从http://openbookproject.net/thinkcs/python/english3e/index.html学习python, 直到现在一切都很好,我刚刚被困了好几个小时.我google了很多但找不到合适的解决方案来解决我的问题所以我在这里.

正如CH17所解释的那样,我试图让OldMaidGame()运行没有问题.http://openbookproject.net/thinkcs/python/english3e/ch17.html - 大部分代码也来自前一章.

我发现的是我无法使用Deck.remove,Hand.remove_matches或任何其他类型的删除功能.经过一些调试后,我发现当程序检查卡片/手/等中是否存在给定卡片时会出现问题.它不可能匹配.然后经过一些回顾章节,(在第16章),我发现'如果卡在甲板/手/等:删除(卡)'等查找.cmp()的对象,以确定卡实际上是否存在于deck/hand/etc中.这是我在电子书给定代码上添加'ace'之后的cmp版本.

def __cmp__(self, other):
    """ Compares cards, returns 1 if greater, -1 if lesser, 0 if equal """
    # check the suits
    if self.suit > other.suit: return 1
    if self.suit < other.suit: return -1
    # suits are the same... check ranks
    # check for aces first.
    if self.rank == 1 and other.rank == 1: return 0
    if self.rank == 1 and other.rank != 1: return 1
    if self.rank != 1 and other.rank == 1: return -1
    # check for non-aces.
    if self.rank > other.rank: return 1
    if self.rank < other.rank: return -1
    # ranks are the same... it's a tie
    return 0
Run Code Online (Sandbox Code Playgroud)

CMP本身似乎罚款据我所知,OFC我可以使用上如何使它更好的(像ACE检查)的一些技巧.所以我不知道为什么牌组/手牌中的牌总是返回假.这是给定的删除功能:

class Deck:
    ...
    def remove(self, card):
        if card in self.cards:
            self.cards.remove(card)
            return True
        else:
            return False
Run Code Online (Sandbox Code Playgroud)

我拼命想让它发挥作用,我想出了这个:

class Deck:
    ...
    def remove(self, card):
        """ Removes the card from the deck, returns true if successful """
        for lol in self.cards:
            if lol.__cmp__(card) == 0:
                self.cards.remove(lol)
                return True
        return False
Run Code Online (Sandbox Code Playgroud)

似乎工作正常,直到我转移到其他非工作删除功能:

class OldMaidHand(Hand):
    def remove_matches(self):
        count = 0
        original_cards = self.cards[:]
        for card in original_cards:
            match = Card(3 - card.suit, card.rank)
            if match in self.cards:
                self.cards.remove(card)
                self.cards.remove(match)
                print("Hand {0}: {1} matches {2}".format(self.name, card, match))
                count = count + 1
        return count
Run Code Online (Sandbox Code Playgroud)

我再次做了一些调整:

class OldMaidHand(Hand):
    def remove_matches(self):
        count = 0
        original_cards = self.cards[:]
        for card in original_cards:
            match = Card(3 - card.suit, card.rank)
            for lol in self.cards:
                if lol.__cmp__(match) == 0:
                    self.cards.remove(card)
                    self.cards.remove(match)
                    print("Hand {0}: {1} matches {2}".format(self.name, card, match))
                    count = count + 1
        return count
Run Code Online (Sandbox Code Playgroud)

删除工作正常,但我尝试删除匹配时会出错(x不在列表中).另一个我们左右,我可能也能做到这一点,但因为我已经感觉我走错了道路,因为我无法修复原来的"卡片在甲板/手/等"等等,我来到这里寻找一些答案/提示.

感谢阅读,我非常感谢你能给予的任何帮助:)

---------------------编辑1 * >

这是我目前的代码:http: //pastebin.com/g77Y4Tjr

---------------------编辑2 * >

我已经尝试过在这里建议的每一个cmp,我仍然无法找到一个带有'in'的卡片.

>>> a = Card(0, 5)
>>> b = Card(0, 1)
>>> c = Card(3, 1)
>>> hand = Hand('Baris')
>>> hand.add(a)
>>> hand.add(b)
>>> hand.add(c)
>>> d = Card(3, 1)
>>> print(hand)
Hand Baris contains
5 of Clubs
 Ace of Clubs
  Ace of Spades
>>> d in hand.cards
False
>>> 
Run Code Online (Sandbox Code Playgroud)

我也尝试过card.py @DSM已经成功使用了,我也遇到了错误,比如它在排序函数中说它无法比较两个卡对象.
所以我想知道,也许这是Python 3.2的问题,或者语法在某处发生了变化?

DSM*_*DSM 6

"所以我想知道,也许这是Python 3.2的一个问题,或者语法在某处发生了变化?"

哦,你在运行Python 3.2? 这将永远不会在Python 3中工作:python 3不使用__cmp__!

查看数据模型(查找__eq__).还读什么在Python 3的新功能对于一些其他的东西它的方式太容易错过.

对不起,这是我们这里的Python程序员; 我们应该早点抓住这个.大多数人可能会查看所有代码,实现甚至没有考虑到源代码显然是python 2代码,并假设这是我们正在使用的.Python 3.2中甚至不存在cmp函数,但是因为__cmp__它永远不会被调用,因此它不会被NameError引发.

如果我在Python 3.2中运行代码,我会完全重现您的问题:

>>> c = Card(0,2)
>>> str(c)
'2 of Clubs'
>>> c in [c]
True
>>> c in Deck().cards
False
Run Code Online (Sandbox Code Playgroud)

在Python 3中,您要么实现所有丰富的cmps,要么实现__eq__其中一个并使用total_ordering装饰器.

from functools import total_ordering

@total_ordering
class Card(object):
    """Represents a standard playing card."""
    suit_names = ["Clubs", "Diamonds", "Hearts", "Spades"]
    rank_names = [None, "Ace", "2", "3", "4", "5", "6", "7", 
              "8", "9", "10", "Jack", "Queen", "King"]
    def __init__(self, suit=0, rank=2):
        self.suit = suit
        self.rank = rank
    def __str__(self):
        return '%s of %s' % (Card.rank_names[self.rank],
                             Card.suit_names[self.suit])
    def __repr__(self): return str(self)
    def __lt__(self, other):
        t1 = self.suit, self.rank
        t2 = other.suit, other.rank
        return t1 < t2
    def __eq__(self, other):
        t1 = self.suit, self.rank
        t2 = other.suit, other.rank
        return t1 == t2


>>> c = Card(2,3)
>>> c
3 of Hearts
>>> c in Deck().cards
True
Run Code Online (Sandbox Code Playgroud)