Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialghaith omar
16,395 PointsHand challenge in python
Hi I am stuck on this challenge, I wrote the code and its work in my work space, but for some reason it didn't pass the challenge:
This is the challenge Now update Hand in hands.py. I'm going to use code similar to Hand.roll(2) and I want to get back an instance of Hand with two D20s rolled in it. I should then be able to call .total on the instance to get the total of the two dice. I'll leave the implementation of all of that up to you. I don't care how you do it, I only care that it works.
I hope any one can help me. Thanks in advance
import random
class Die:
def __init__(self, sides=2):
if sides < 2:
raise ValueError("Can't have fewer than two sides")
self.sides = sides
self.value = random.randint(1, sides)
def __int__(self):
return self.value
def __add__(self, other):
return int(self) + other
def __radd__(self, other):
return self + other
class D20(Die):
def __init__(self):
super().__init__(sides=20)
from dice import D20
class Hand(list):
def roll(self, size=0, die_class=D20, *args, **kwargs):
super().__init__()
for _ in range(size):
self.append(die_class())
self.sort()
return self
@property
def total(self):
return sum(self)
2 Answers
Steven Parker
231,269 PointsHere's a few hints:
- you might try implementing roll as a class method, as it won't be called on an instance
- remember to instantiate a new Hand and return it
- you can't sort a Hand, because neither D20 or Die implement
__cmp__
which it needs - the instructions don't require the hand to be sorted anyway
Casey Nord
12,141 PointsThis helped me a lot. I had very similar code to Ghaith's original post. I still don't understand class methods that well but after awhile I think I picked up on a hint in the challenge question:
"I'm going to use code similar to Hand.roll(2)"
The question asks to use the command Hand.roll() with a capital H. This would imply that we don't want to create an instance of the class, but that we want to be able to call the class directly, is that correct? That would point to using a class method. The expected output in the shell would be:
>>> Hand.roll(2)
[16, 20]
I played with it for a while though and couldn't figure out how to get my code to work. I found this post and it really helped me out, but there still a few other things I'm wondering about:
The original code I had been trying looked like this and didn't pass:
from dice import D20
class Hand(list):
def __init__(self, size=0, die_class=D20, *args, **kwargs):
super().__init__()
@classmethod
def roll(cls, size, die_class=D20):
new_hand = []
for _ in range(size):
new_hand.append(die_class())
return cls(hand)
@property
def total(self):
return sum(self)
after finding this post I was able to correct my code to pass the challenge:
from dice import D20
class Hand(list):
def __init__(self, new_hand):
super().__init__()
self.extend(new_hand)
@classmethod
def roll(cls, size, die_class=D20):
new_hand = []
for _ in range(size):
new_hand.append(die_class())
return cls(new_hand)
@property
def total(self):
return sum(self)
The questions I still have are:
- Including args and kwargs in the arguments of the init method was giving me a "Hand doesn't return the correct total" error. Why is this? I had to remove the arguments altogether to pass the challenge.
- I didn't expect to use the .extend() in the init method. I'm confused as to exactly why it was necessary to move all of my original init arguments to my classmethod and why it was necessary to include the list I created (new_hand) in the arguments of the init method along with self.extend(new_hand).
Steven Parker
231,269 PointsThe answer to both questions is that by overriding __init__
, you took on the responsibility for compatibility with what it did before, which meant both handling the passed argument the same way and not requiring additional ones.
ghaith omar
16,395 PointsHi I am glade that my question helped you. I think the answer of your second question that you cant roll the dice without the size and die class, so in order to roll the dice with class method you must take in the class method the 2 argument size and die class. In this case there is no need in your original class to use the size and die class as an argument again. your class method will return a list of 2 number as a value to the class to be used in the class, that's why you must use .extend not .append.
For your first question I don't think I can answer you, I hope that I was able to help you.
Christopher Carucci
1,971 PointsI like you, you research, Thanks for saving me a lot of time and posting a lot of examples.
ghaith omar
16,395 Pointsghaith omar
16,395 PointsThanks for the answer.
I wasn't fully understand the classmethod, after some reading its now clear what the task request and what you say. so thanks for the explanation.
this is now my answer:
from dice import D20
class Hand(list):