Question

I have built a class below with a constructor. The idea is that a PlayingCard object should be generated randomly by default if a rank and/or suit is not specified. In the event that an invalid suit or rank is specified, an object should not be created. I believe this is working, but I am not sure what to make of the exception. I wanted to verify that the only exception thrown in case of an invalid rank or suit is the one that I specified. I am confused why there is a 'NameError' that says the instance has no attribute 'suit' as I did not specify this when I wrote the raise statement.

Also, I would like to make the class flexible so that user defined rank and suit do not need to be passed in as strings when creating an instance, but I cannot seem to get it to work. If anybody could point me in the right direction or explain why I would not want to do this, it would be appreciated.

class PlayingCard:
    ranks = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
    suits = ['Spades', 'Hearts', 'Clubs', 'Diamonds']

    def __init__(self, rank = None, suit = None):
        if rank is None: self.rank = PlayingCard.ranks[rand.randint(0,12)]
        elif rank in PlayingCard.ranks: self.rank = rank


        if suit is None: self.suit = PlayingCard.suits[rand.randint(0,3)]
        elif suit in PlayingCard.suits: self.suit = suit


        if self.rank not in PlayingCard.ranks or self.suit not in PlayingCard.suits: raise NameError('Invalid Suit or Rank')


>>> c1 = PlayingCard('15','Diamonds')

Traceback (most recent call last):
  File "<pyshell#63>", line 1, in <module>
    c1 = PlayingCard('15','Diamonds')
  File "C:\Python27\poker.py", line 26, in __init__
    if self.rank not in PlayingCard.ranks or self.suit not in PlayingCard.suits: raise NameError('Invalid Suit or Rank')
AttributeError: PlayingCard instance has no attribute 'rank'

>>> c2 = PlayingCard('A', 'Swords')

Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    c2 = PlayingCard('A', 'Swords')
  File "C:\Python27\poker.py", line 26, in __init__
    if self.rank not in PlayingCard.ranks or self.suit not in PlayingCard.suits: raise NameError('Invalid Suit or Rank')
AttributeError: PlayingCard instance has no attribute 'suit'
Was it helpful?

Solution

When rank is not None and also not in ranks, self.rank is never set and so

if self.rank not in PlayingCard.ranks

won’t work; self.rank doesn’t exist. Same goes for suit. You could be more specific with the error and solve the problem all at once:

def __init__(self, rank = None, suit = None):
    if rank is None: self.rank = PlayingCard.ranks[rand.randint(0,12)]
    elif rank in PlayingCard.ranks: self.rank = rank
    else: raise NameError('Invalid rank')

    if suit is None: self.suit = PlayingCard.suits[rand.randint(0,3)]
    elif suit in PlayingCard.suits: self.suit = suit
    else: raise NameError('Invalid suit')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top