Python Count方法:它可以接受对象属性引用吗?

时间:2013-09-22 14:57:05

标签: python oop object count

前一段时间我用Javascript构建了一个简单的扑克游戏,并且认为我在Python中从零开始。这是迄今为止的代码(您可以跳到最后来解决问题):

#imports
import random
#basics
values = range(2,15)
suits = ['Clubs','Spades','Diamonds','Hearts']
#card object
class Card:
    def __init__(self,suit,value,name):
        self.suit = suit
        self.value = value
        self.name = name
        if self.value < 11:
            self.name = str(self.value) + ' of'
        if self.value == 11:
            self.name = 'Jack of'
        if self.value == 12:
            self.name = 'Queen of'
        if self.value == 13:
            self.name = 'King of'
        if self.value == 14:
            self.name = 'Ace of'
#deck
deck = []
#load and shuffle deck
for s in suits:
    for v in values:
        deck.append(Card(s,v,'o'))
random.shuffle(deck)
#load hands
your_hand = random.sample(deck,7)
for card in your_hand:
    deck.remove(card)
#determine hands
def find_matches(hand):
    class Match:
        def __init__(self,value,amount):
            self.value = value
            self.amount = amount
    matches = [Match(card.value,hand.count(card.value)) for card in hand]
    for x in matches:
        print x.value,x.amount
find_matches(your_hand)

是的,我意识到它并不完美(建议总是受到赞赏!)。我的问题是提供可靠的匹配功能。我已经尝试了一些不同的方法,但是对于每个元素,hand.count(card.value)为{0}。问题是count方法接受哪些参数的问题?或者它是我的代码的一个方面?

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

hand.count(card.value)将检查卡片中card.value出现的次数。这是0,因为该值是一个数字,并且在牌组中没有数字,只有Card s。

您可以sum(card.value == 5 for card in hand)获取hand card.value == 5所在的卡片数量。这是有效的,因为a == b具有布尔值TrueFalse,它们在数值上分别等于10

所以它遍历手(for card in hand),进行比较(card.value == 5)并总结True的数量,虽然它是内联的,所以存储了一个列表在记忆中。

答案 1 :(得分:2)

hand.count(card.value)的问题在于它计算手中有多少Card个对象等于其中一个对象的整数值,因为你比较两个不同的对象,它总是为零。一个简单的解决方法是将所有整数卡值提取到一个单独的列表中,并使用count()方法代替:

def find_matches(hand):
    class Match:
        def __init__(self, value, amount):
            self.value = value
            self.amount = amount
    values = [card.value for card in hand]  # list of extracted card values
    matches = [Match(card.value, values.count(card.value)) for card in hand]
    for x in matches:
        print x.value, x.amount

通过此更改,它将执行以下操作:

10 1
4 1
9 1
3 1
12 2
12 2
6 1

更类似于Pythonic的方法是使用带有生成器表达式的collections.Counter类:

from collections import Counter

counter = Counter(card.value for card in your_hand)
print '{} unique values: {}'.format(len(counter), counter)

同一只手会给你:

6 unique values: Counter({12: 2, 3: 1, 4: 1, 6: 1, 9: 1, 10: 1})

我认为在评估指针时使用它会更容易(它是字典的子类)。

答案 2 :(得分:2)

你的问题得到了很好的解答,所以这里还有其他一些评论:

首先,if中的Card.__init__()的snaky链更好地被字典查找取代。喜欢这样做:

value2name = dict((val, str(val)) for val in values)
for val, name in (11, 'Jack'), (12, "Queen"), (13, "King"), (14, "Ace"):
    value2name[val] = name

设置values后,将所有__init__()替换为:

        self.name = value2name[value] + " of " + suit

然后some_card.name将显示为(例如):

King of Spades
5 of Spades
Ace of Hearts
[etc]

其次,如果您使用random.shuffle(),则使用random.sample() 没有意义 - 反之亦然。只使用一个。由于您可能希望以后剥离其他人,shuffle()会更好。在洗牌后,可以非常有效地从牌组中移除7张随机牌:

your_hand = deck[-7:]
del deck[-7:]

在CPython中,从列表的 end 中删除切片非常有效。实际上,实现只是记录列表的大小现在因删除的元素数量而变小 - 不需要重新排列。

要获得另外7张牌,请执行相同的操作。或者把它放在一个函数中:

def deal(deck, n):
    if n <= 0:
        raise ValueError("n must be > 0")
    if n > len(deck):
        raise ValueError("asked for more cards than remain")
    result = deck[-n:]
    del deck[-n:]
    return result

然后:

your_hand = deal(deck, 7)

后。

玩得开心! : - )