0

I have the following code and cant seem to realized why I get this error: Traceback (most recent call last):

card_ranks = [c.rank for c in cards[i:i+5]]
AttributeError: 'str' object has no attribute 'rank'

Here's the code:

import random
import logging
from collections import OrderedDict
from const import __version__, suits, ranks, POS_TOP, POS_BOTTOM
logger = logging.getLogger(__name__)
def f_list(lst, sep=','):
 return sep.join([str(x) for x in lst])
def f_lists(lst, sep=' / '):
 return f_list(map(f_list, lst), sep)
class Card(object):
 """Represents a single french-design card with it's rank and suit.
 Cards can be compared and ordered by rank. A card, relative to
 a card of the same rank but different suit, is compared as neither
 higher, lower nor equal.
 :param rank: Either the rank (one of 'A', 'K', 'Q', 'J', 'T', '9', ... '2')
 or rank and suit together (e.g. 'AS', '8H', etc.)
 :type rank: str
 :param suit: The suit, if not given as one string with rank
 (one of 'S', 'H', 'C', 'D' for spade, heart, club or diamond)
 :type suit: str
 :raises: ValueError
 """
 def __init__(self, rank, suit=None):
 if suit is None:
 suit = rank[1]
 rank = rank[0]
 if rank not in ranks:
 raise ValueError('Card(): Invalid rank')
 if suit not in suits:
 raise ValueError('Card(): Invalid suit')
 self.rank = rank
 self.suit = suit
 @classmethod
 def card_list(cls, *args):
 """Create a list of new cards.
 Each argument should describe one card with rank and suit together.
 :param args: One or more cards.
 :type rank: str
 :returns: List of new cards, one for each input parameter.
 :rtype: list of :class:`pokercards.cards.Card` objects
 :raises: ValueError
 """
 lst = []
 for c in args:
 lst.append(cls(c))
 return lst
 def __str__(self):
 return self.rank + self.suit
 def __repr__(self):
 return 'Card(%s, %s)' % (self.rank, self.suit)
 def __hash__(self):
 return (ord(self.rank) << 8) + ord(self.suit)
 def __eq__(self, obj):
 return self.rank == obj.rank and self.suit == obj.suit
 def __ne__(self, obj):
 return self.rank != obj.rank or self.suit != obj.suit
 def __lt__(self, obj):
 return ranks.index(self.rank) > ranks.index(obj.rank)
 def __gt__(self, obj):
 return ranks.index(self.rank) < ranks.index(obj.rank)
 def __le__(self, obj):
 return ranks.index(self.rank) >= ranks.index(obj.rank)
 def __ge__(self, obj):
 return ranks.index(self.rank) <= ranks.index(obj.rank)
class Deck(object):
 """Represents a single deck of 52 :class:`card.Card` objects.
 The deck could be imagined face down on a table. All internal lists
 represent the cards in order from bottom up. So dealing the top
 card means poping last item from the list.
 """
 def __init__(self):
 self.popped = []
 self.discarded = []
 self.active = []
 for s in suits:
 for r in ranks:
 self.active.append(Card(r, s))
 def shuffle(self):
 """Shuffle the deck."""
 random.shuffle(self.active)
 def pop(self):
 """Deal the top card from the deck.
 :returns: :class:`pokercards.cards.Card` instance
 """
 card = self.active.pop()
 self.popped.append(card)
 return card
 def discard(self):
 card = self.active.pop()
 self.discarded.append(card)
 def return_cards(self, cards, pos = POS_BOTTOM):
 if pos not in (POS_BOTTOM, POS_TOP):
 raise Exception('Deck.return_cards(): invalid pos parameter')
 for card in cards[:]:
 if card in self.discarded:
 self.discarded.remove(card)
 elif card in self.popped:
 self.popped.remove(card)
 else:
 raise Exception('Deck.return_cards(): card not among removed cards')
 if pos == POS_BOTTOM:
 self.active[0:0] = [card]
 else:
 self.active.append(card)
 def return_discarded(self, pos = POS_BOTTOM):
 self.return_cards(self.discarded, pos)
 def return_popped(self, pos = POS_BOTTOM):
 self.return_cards(self.popped, pos)
 def return_all(self, pos = POS_BOTTOM):
 self.return_popped()
 self.return_discarded()
 def stats(self):
 return (len(self.active), len(self.popped), len(self.discarded))
 def __str__(self):
 return '[%s]' % ' '.join((str(card) for card in self.active))
 def __repr__(self):
 return 'Deck(%s)' % self.__str__()
class PokerHand(object):
 """Compute the best hand from given cards, implementing traditional
 "high" poker hand ranks.
 The hand object can be given more than five cards (as in Texas
 Hold'em or similar variants) and the evaluation will pick the best
 hand.
 Evaluated :class:`pokercards.cards.PokerHand` objects are
 compared and sorted by the rank of the hand.
 .. attribute:: cards
 List of :class:`pokercards.cards.Card` objects to make the hand
 from. The :meth:`pokercards.cards.PokerHand.evaluate` method
 should be called after manual update to re-evaluate the updated
 hand.
 Following attributes are available after evaluating the hand.
 .. attribute:: hand_rank
 Readonly rank of the hand (0 = high card to 8 = straight flush)
 .. attribute:: hand_cards
 Readonly list of cards which complete the rank.
 .. attribute:: kickers
 Readonly list of extra cards which can break a tie.
 :param cards: List of :class:`pokercards.cards.Card` objects.
 :param evaluate: Evaluate the hand when creating.
 :type evaluate: bool
 """
 def __init__(self, cards, evaluate=True):
 cards.sort(reverse=True)
 self.cards = cards
 if evaluate:
 self.evaluate()
 def evaluate(self):
 """Evaluate the rank of the hand.
 Should be called either implicitly at start by leaving
 parameter ``evaluate`` True when creating the hand or
 explicitly by calling this method later, e.g. after changing
 the :attr:`cards` attribute manually.
 """
 self._eval_hand_rank()
 self._fill_kickers()
 def _by_rank(self, cards=None):
 if cards is None:
 cards = self.cards
 ranked = OrderedDict()
 for card in cards:
 if card.rank in ranked:
 ranked[card.rank].append(card)
 else:
 ranked[card.rank] = [card]
 return ranked
 def _by_suit(self, cards=None):
 if cards is None:
 cards = self.cards
 suited = OrderedDict()
 for card in cards:
 if card.suit in suited:
 suited[card.suit].append(card)
 else:
 suited[card.suit] = [card]
 return suited
 def _find_flushes(self, cards=None):
 if cards is None:
 cards = self.cards
 flushes = []
 for cards in self._by_suit(cards).values():
 l = len(cards)
 if l >= 5:
 for i in xrange(0, l - 4):
 flushes.append(cards[i:i+5])
 return flushes
 def _find_straights(self, cards=None):
 if cards is None:
 cards = self.cards
 straights = []
 for i in xrange(0, len(cards) - 4):
 card_ranks = [c.rank for c in cards[i:i+5]]
 j = ranks.index(card_ranks[0])
 if card_ranks == ranks[j:j+5]:
 straights.append(cards[i:i+5])
 return straights
 def _fill_kickers(self):
 hand_count = len(self.hand_cards)
 kicker_count = 5 - hand_count
 if kicker_count > 0:
 kickers = self.cards[:]
 for card in self.hand_cards:
 kickers.remove(card)
 self.kickers = kickers[:kicker_count]
 else:
 self.kickers = []
 logger.debug("kickers: %s", f_list(self.kickers))
 logger.debug("--- -------------- ---")
 def _eval_hand_rank(self):
 logger.debug("--- Evaluating %s ---", f_list(self.cards))
 straights = self._find_straights()
 if straights: logger.debug( "straights: %s", f_lists(straights))
 flushes = self._find_flushes()
 if flushes: logger.debug("flushes: %s", f_lists(flushes))
 pairs = []
 threes = []
 fours = []
 for cards in self._by_rank().values():
 l = len(cards)
 if l >= 4:
 fours.append(cards[0:4])
 elif l == 3:
 threes.append(cards)
 elif l == 2:
 pairs.append(cards)
 if pairs: logger.debug("pairs: %s", f_lists(pairs))
 if threes: logger.debug("threes: %s", f_lists(threes))
 if fours: logger.debug("fours: %s", f_lists(fours))
 # straight flush
 for cards in straights:
 if cards in flushes:
 self.hand_rank = 8
 self.hand_cards = cards
 logger.debug("* straight flush: %s", f_list(self.hand_cards))
 return
 # four of a kind
 if len(fours) > 0:
 self.hand_rank = 7
 self.hand_cards = fours[0]
 logger.debug("* four of a kind: %s", f_list(self.hand_cards))
 return
 # full house
 if len(threes) > 1:
 self.hand_rank = 6
 self.hand_cards = threes[0] + threes[1][:2]
 logger.debug("* full house: %s", f_list(self.hand_cards))
 return
 elif len(threes) == 1 and len(pairs) > 0:
 self.hand_rank = 6
 self.hand_cards = threes[0] + pairs[0]
 logger.debug("* full house: %s", f_list(self.hand_cards))
 return
 # flush
 if len(flushes) > 0:
 self.hand_rank = 5
 self.hand_cards = flushes[0]
 logger.debug("* flush: %s", f_list(self.hand_cards))
 return
 # straight
 if len(straights) > 0:
 self.hand_rank = 4
 self.hand_cards = straights[0]
 logger.debug("* straight: %s", f_list(self.hand_cards))
 return
 # three of a kind
 if len(threes) > 0:
 self.hand_rank = 3
 self.hand_cards = threes[0]
 logger.debug("* three of a kind: %s", f_list(self.hand_cards))
 return
 # two pair
 if len(pairs) > 1:
 self.hand_rank = 2
 self.hand_cards = pairs[0] + pairs[1]
 logger.debug("* two pairs: %s", f_list(self.hand_cards))
 return
 # one pair
 if len(pairs) == 1:
 self.hand_rank = 1
 self.hand_cards = pairs[0];
 logger.debug("* two of a kind: %s", f_list(self.hand_cards))
 return
 # high card
 self.hand_rank = 0
 self.hand_cards = [self.cards[0]]
 logger.debug("* high card: %s", f_list(self.hand_cards))
 def __str__(self):
 return '[%s]' % f_list(self.cards)
 def __repr__(self):
 return '%s(%s)' % (self.__class__.__name__, self.__str__())
 def __cmp__(self, other):
 if self.hand_rank > other.hand_rank:
 return 1
 elif self.hand_rank < other.hand_rank:
 return -1
 else:
 # same rank
 for c1, c2 in zip(self.hand_cards, other.hand_cards):
 if c1 > c2:
 return 1
 elif c1 < c2:
 return -1
 else:
 # same cards, check kickers
 for c1, c2 in zip(self.kickers, other.kickers):
 if c1 > c2:
 return 1
 elif c1 < c2:
 return -1
 # really, a tie
 return 0
deck = Deck()
deck.shuffle()
player = []
computer = []
cmoney = 500
money = 500
pot = 0
for i in range(5):
 card = deck.pop()
 player.append(str(card))
player.sort()
for i in range(5):
 card = deck.pop()
 computer.append(str(card))
computer.sort()
pot += 10
money -= 5
cmoney -= 5
print "All players have anted 5ドル."
print "Your Hand:", player
print "Your Money: $" + str(money)
print "Pot: $" + str(pot)
discard = []
ask = raw_input("Bet or check? ")
if ask.lower() == "bet":
 ask2 = int(raw_input("How much? "))
 if ask2 > money:
 print "You don't have that much money!"
 else:
 money -= ask2
 cmoney -= ask2
 pot += ask2 * 2
print("Pot: $" + str(pot))
ui = raw_input("Do you want to discard some cards? ")
if ui.lower() == "yes":
 ui2 = int(raw_input("How many? "))
 for i in range(ui2):
 ui3 = raw_input("Card " + str(i + 1) + ": ")
 discard.append(ui3)
 player.pop()
 for i in range(ui2):
 card = deck.pop()
 player.append(str(card))
print "Your Hand:", player
print "Your Money: $" + str(money)
ask3 = raw_input("Bet or check? ")
if ask3.lower() == "bet":
 ask4 = int(raw_input("How much? ")) 
 if ask4 > money:
 print "You don't have that much money!"
 else:
 money -= ask4 
 pot += ask4
pval = PokerHand(player, True)
cval = PokerHand(computer, True)
if pval > cval:
 print "YOU WIN!"
 money += pot
 pot = 0
else:
 print "YOU LOSE!"
 cmoney += pot
 pot = 0
print "Pot: $" + str(pot)
print "Your Hand:", player
print "Computer\'s Hand:", computer
08Dc91wk
4,3388 gold badges37 silver badges68 bronze badges
asked Jun 23, 2015 at 20:00
5
  • Could you post the code where you introduce the cards list? Commented Jun 23, 2015 at 20:04
  • Could you print the cards list and show the output? Commented Jun 23, 2015 at 20:04
  • 1
    Add self to your class "member" variables. Right now rank is simply a variable within the scope of the class, not a member; so when you try to access it outside of the class ([c.rank...]) it cannot find the rank field Commented Jun 23, 2015 at 20:04
  • 2
    Could you read How to Ask and follow its advice? Commented Jun 23, 2015 at 20:05
  • [2S 7C 6S 6H KS 9S TS KH 4S 3S AC QC JS KC 6D AH TD 8D TH 4C 4D 8C QD 3H 4H KD 7H 5S 7S 3C JH 3D 9H 2D 2C 2H QH 7D 6C 5H TC AS] Commented Jun 23, 2015 at 21:05

1 Answer 1

1

You are constructing the PokerHand with an array of strings, not an array of cards. The code is here:

for i in range(5):
 card = deck.pop()
 player.append(str(card))
player.sort()
for i in range(5):
 card = deck.pop()
 computer.append(str(card))
computer.sort()

Instead of str(card), try just using append(card). Hopefully that should work, unless you use the string elsewhere.

answered Jun 23, 2015 at 20:09
Sign up to request clarification or add additional context in comments.

1 Comment

when i do that, it adds 'Card(A , S)' instead of 'AS'

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.