Reputation: 33
I've created a class called Card, which takes a number and gives the following output depending on the methods called:
class Card:
def __init__(self, number):
self.number = number
def suit(self):
if self.number in range(0, 13):
return 0
elif self.number in range(13, 26):
return 1
elif self.number in range(26, 39):
return 2
elif self.number in range(39, 52):
return 3
def rank(self):
if self.number in range(0, 13):
return self.number
elif self.number in range(13, 26):
return self.number - 13
elif self.number in range(26, 39):
return self.number - 26
elif self.number in range(39, 52):
return self.number - 39
def points(self):
if self.number in (12,25,38,51):
return 4
elif self.number in (11,24,37,50):
return 3
elif self.number in (10,23,36,49):
return 2
elif self.number in (9,22,35,48):
return 1
else:
return 0
def __repr__(self):
ranks = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
if self.number in range(0, 13):
return ranks[self.number] + '\u2663'
elif self.number in range(13, 26):
return ranks[self.number - 13] + '\u2666'
elif self.number in range(26, 39):
return ranks[self.number - 26] + '\u2665'
elif self.number in range(39, 52):
return ranks[self.number - 39] + '\u2660'
def __lt__(self,other):
if str(self.rank) < str(other.rank):
return True
else:
return False
* any tips on making the code better are appreciated
Now I have to write a class called BlackjackCard with Card class inherited:
class BlackjackCard(Card):
def __init__(self, number):
Card.__init__(self, number)
def points(self):
if self.rank == 12:
return 11
elif self.rank in (11,10,9):
return 10
elif self.rank < 11:
return self.rank
I am trying to overload the method points() by rewriting but I can't seem to implement self.rank from class Card.
When I assign y = BlackjackCard(38)
and executey.points()
, it gives me a type error: unorderable types: method() < int()
.
What am I doing wrong here?
Upvotes: 0
Views: 65
Reputation: 10298
Ignacio's answer is the right one (using property
), but in terms of improving your code in general, a few suggestions.
First, instead of if foo in range(a, b):
, you can just do if a <= foo < b:
But in your case, you can simplify this further using math. The suit is just floor(number/13)
, or more simply number//13
. Similarly, the rank is the the remainder of number/13
, the modulo of 13, which is number%13
.
Second, rather than re-calculate everything every time, you can re-use the result of one method in another. For example, you re-calculate the suit in __repr__
.
Finally, boolean tests in python, like x < y
, resolve to True
or False
. So rather than return True
if the test passes and False
if it doesn't, you can just return the result of the test exactly.
Also, I don't think you want to return the str
of the rank in __lt__
, but rather the numerical rank.
So here is my improved version:
class Card:
def __init__(self, number):
self.number = number
@property
def suit(self):
return self.number // 13
@property
def rank(self):
return self.number % 13
@property
def points(self):
return max(0, self.rank-8)
@property
def suit_str(self):
suits = ['\u2663', '\u2666', '\u2665', '\u2660']
return suites[self.suit]
@property
def rank_str(self):
ranks = {9: 'J', 10: 'Q', 11: 'K', 12: 'A'}
return ranks.get(self.rank, str(self.rank+2))
def __repr__(self):
return self.rank_str+self.suit_str
def __lt__(self, other):
return self.rank < other.rank
Upvotes: 0
Reputation: 798606
self.rank
is a method. Either call it by adding parens (self.rank()
), or convert it into a property.
Upvotes: 2