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'
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')