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 trialRohit Gopalan
81,945 PointsUnable to create a roll method in Hand
I am having trouble getting this method to work. It would be great if I could get some pointers on how to solve this issue.
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,size=20):
super().__init__(size)
from dice import D20
class Hand(list):
@property
def total(self):
return sum(self)
def __init__(self, size=0, die_class=None, *args, **kwargs):
if not die_class:
raise ValueError("You must provide a die class")
super().__init__()
for _ in range(size):
self.append(die_class())
self.sort()
def roll(self,size=2):
return self.__init__(size,D20())
Rohit Gopalan
81,945 PointsI made the change from size to sides in the dice.py class but I am still unable to get the roll method to work.
Zachary Canter
20,530 PointsYeah man the directions for this one are sort of confusing . Hoping for some help myself. Kenneth Love
Zachary Canter
20,530 Points class Hand(list):
@property
def total(self):
return sum(self)
def __init__(self, size=0, die_class=None, *args, **kwargs):
if not die_class:
raise ValueError("You must provide a die class")
super().__init__()
for _ in range(size):
self.append(die_class())
@classmethod
def roll(cls, size=2):
return cls(size=size, die_class=D20)
14 Answers
Assma Al-Adawi
8,723 PointsCan anyone provide a method for thinking through this problem? All throughout this course I have had issues with the code challenges because I cannot seem to come up with the methodology to approach these problems based on what I learned in the videos. I usually just de-construct some else's answer and try to understand how they come up with it. This case is no different: I cannot even begin to think about how to approach this!
Ryan Cross
5,742 PointsThere's gaps for sure. I've found that sometimes I'll get what he means and sometimes no luck. I head to other outside resources like a book or youtube and will get it. On return to the course after I reach understanding I'll rewatch the video and often say, well of course i didn't get it here... there's problems! Nobody's perfect and I imagine that its quite a stretch for someone very advanced to completely see it from the perspective of a stone cold noob.
ursaminor
11,271 PointsAssma Al-Adawi This took me a while, but I finally figured it out.
Let's break down the problem. It states: "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."
The first thing to do is carefully read the problem and restate it to make sure you understand what is being asked. For example, "I need to write a method called roll() which takes a number and creates that many D20 dice. The total() method uses sum() to add up the dice values. Sum() takes an iterable, like a list. So the roll() method will create a list of dice, which makes sense because Hand is a subclass of list." Something like that.
The clue that Kenneth gave was that you're going to call it on Hand (the class), not an instance of Hand. What kind of method do you call directly on the class?
The books.py example from earlier in the course was helpful. Take a look at that and try to solve it before reading further.
class Bookcase:
def __init(self, books=None):
self.books = books
@classmethod
def create_bookcase(cls, book_list):
books = []
for title, author in book_list:
books.append(Book(title, author))
return cls(books)
As others already pointed out, it's a class method, so you put the @classmethod decorator above the class declaration. Class methods don't take self, but cls as the first argument, because you're calling it on the class, not an instance (self). Then you would put in the other argument, which is the number of dice you're creating. You can call that size.
Then, for that many (you can call range() on size), you're going to create a D20 die. So you'll need a for loop and inside the loop you'll create a die. How do you create a D20 die?
Since the function needs to return a list, the dice will need to be appended to a list. You can initialize an empty list and then append to it inside the for loop.
Finally, you'll need to return the list of dice and call cls() on the list to convert it into a Hand. (Is that correct Kenneth Love ? I couldn't find the explanation in the Python docs.)
To test the code, you can try:
Hand.roll(2).total
Kenneth Love
Treehouse Guest TeacherRead the instructions again. My example code was Hand.roll(2)
. What isn't being created in the example? What kind of method does roll
need to be?
Zachary Canter
20,530 PointsThanks a ton for getting back so quickly. Really stuck!! Can't figure it out :( Could we get another hint?
Kenneth Love
Treehouse Guest TeacherAnswer my question :) Talk through this. I'm sure you can get it.
Wayne Smith
16,158 Points"Read the instructions again" is pretty poor in terms of response when one of the major issues is the instructions being written in a terribly confusing way.
Ankoor Bhagat
1,098 PointsOne of the worst challenges ever. My solution works on Jupyter Notebook but here I get Bummer! Can't get the length of a 'Hand'
. This OOP course sucks! Here is my solution that works on Jupyter Notebook:
from dice import D20
class Hand(list):
def __init__(self, size=0, die_class=None, *args, **kwargs):
if not die_class:
raise ValueError("die_class must be provided.")
super().__init__()
for _ in range(size):
self.append(die_class()) # Creating instances of die_class
# Sorting
self.sort()
@classmethod
def roll(cls, size, die_class=D20):
return cls(size=size, die_class=die_class)
@property
def total(self):
return sum(self)
h = Hand.roll(2)
print('Length: ', len(h))
print('Hand: ', h)
print('Total: ', h.total)
>>> Length: 2
>>> Hand: [14, 18]
>>> Total: 32
keith rezendes
4,459 PointsAgreed. course was great till this OOP portion. Almost gave up, just want to get this done. Not sure what is it, just too much info?
Michael Cook
Full Stack JavaScript Techdegree Graduate 28,975 PointsTaking this now, totally agree. I came into Python already knowing OOP JavaScript and having a decent programming foundation already. This course has managed to confuse me non-stop. Information is presented poorly, little context in terms of real-world usage, unclear explanation, I could go on. I hate to say it because I know Kenneth is a smart and accomplished guy and I have a lot of respect for him, but I think this course could have been done a lot better. I was thinking of repeating the entire course once finished, but instead I am gonna get a good book on Python and read the OOP chapter(s).
thebong
10,899 PointsHere is my solution, I only post this as reference for people stuck on the challenge. There are other approaches in this thread but they are either too clunky or use concepts I'm not very strong on (classmethods). Happy learning!
'''python
from dice import D20
class Hand(list): @property def total(self): return sum(self)
def __init__(self, size = 0, *args, **kwargs): //We dont really care about initialisation because the roll function is important here
super().__init__()
def roll(self, size):
for x in range(size):
self.append(int(D20())) // appending with the value of each dice to the Hand Object
'''
Rohit Gopalan
81,945 PointsI just used your code and added the following lines:
h = Hand.roll(2) t = h.total
and it worked fine for me. Thanks for your help in resolving this issue Zac.
Paul Bentham
24,090 PointsZachary, in your explanation I think it would be clearer if you set size = 0 in your roll class method... If my understanding is correct if you have 2 it means the default for roll would always be 2 so if you called Hand.roll() you'd always get that answer.
Thanks for plugging away at this though, it had me stuck for a while!
Rohit Gopalan
81,945 PointsI tried the following code and was unable to get this working:
from dice import D20
class Hand(list): @property def total(self): return sum(self)
def __init__(self, sides=0, die_class=None, *args, **kwargs):
if not die_class:
raise ValueError("You must provide a die class")
super().__init__()
for _ in range(sides):
self.append(die_class())
@classmethod
def roll(cls, sides=2):
return cls(sides=sides, die_class=D20)
h = Hand.roll(2) t = h.total
Could someone please tell me what I am missing with this code?
Zachary Canter
20,530 PointsYa idk what to tell you man. Works find for me. Here is my entire hands file
from dice import D20
class Hand(list):
def __init__(self, size=0, die_class=D20):
super().__init__()
for _ in range(size):
self.append(die_class())
@classmethod
def roll(cls, size=2):
return cls(size=size)
@property
def total(self):
return sum(self)
Miriana Moura
9,633 PointsAfter a crazy amount of frustration, I figured it out.
from dice import D20
class Hand(list):
def __init__(self, size=0, die_class=D20, *args, **kwargs):
super().__init__()
for _ in range(size):
self.append(die_class())
@classmethod
def roll(cls, size=2):
return cls(size=size)
@property
def total(self):
return sum(self)
Mike Siwik
Full Stack JavaScript Techdegree Student 8,483 Pointswow... you just saved this rookie a lot of work
Zachary Canter
20,530 PointsYou were right. I forgot about classmethods. Thank you for all you do here at Treehouse! Your courses are excellent.
devin leyba
7,209 PointsTerribly taught course. Need to redo Treehouse.
Jassim Alhatem
20,883 PointsI thought it was pretty good tbh. I had to research on my own sometimes. But that's how programming works.
To be fair though, the challenges are wack, and sometimes pointless. So what I advise you to do, after every course create a project using the tools that you had learnt from that course.
Mahdi Jafari
17,887 PointsHere what I read found working thanks to community here, I have some knowledge about Java and OOP but this course not helpfull much.
from dice import D20
class Hand(list):
def __init__(self, size=0, die_class=D20):
super().__init__()
for _ in range(size):
self.append(die_class())
@classmethod
def roll(cls, size=2):
return cls(size=size)
@property
def total(self):
return sum(self)
mourad marzouk
5,560 PointsHey guys, not sure who this is still a problem for. But I just looked through all of this and and using the last bit of code I cam up for the answer.
@zachary looked like he had it right.
Only thing I changed is in def roll, I only passes size as is. So like this
def roll(cls, size): return cls(size)
Everything else is the same.
I didn't think of setting the die_class=D20 in the init, I was doing it in the roll with a super like the video,
Also not sure why I didnt use cls as a parameter in the roll().
I'm actually still not sure why that's there.
Christopher Ransom
11,602 Pointsfrom dice import D20
class Hand(list):
@property
def total(self):
return sum(self)
@classmethod
def roll(cls, size):
empty = []
for i in range(size):
i = D20()
empty.append(i)
return cls(empty)
This is the solution, ursaminor really helped me out with calling cls() on the list at the end. I still dont understand what that does, but the rest of the thinking makes sense to me.
Jassim Alhatem
20,883 PointsThis course is pretty bad IMO. That's why you don't understand what it does. class methods are actually very helpful and you'll use them in many projects in the future. Anyways, check out Real Python. They have one of the best explanations for this concept.
Brendon Van der nest
12,826 Pointsfrom dice import D20
class Hand(list):
def __init__(self, size=0, die_class=None, *args, **kwargs):
self.size = size
super().__init__()
for _ in range(size):
self.append(die_class()) # Creating instances of die_class
@classmethod
def roll(cls, size, die_class=D20):
return cls(size=size, die_class=die_class)
@property
def total(self):
return sum(self)
Gerald Wells
12,763 PointsGerald Wells
12,763 PointsIt should automatically have 20 sides not size