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 trialJohannes Scribante
19,175 PointsPart 2 of code challenge, 1. cannot get length of hand and 2. passing a class as argument on the class's method
I have implemented this code locally and here are the scenario's I have tested.
h20 = Hand(size=5)
print(h20)
# output: [17, 10, 17, 9, 2]
print(h20.total)
# output: 55
h20.roll(4)
print(h20)
# output: [8, 17, 20, 2]
print(h20.total)
# output: 47
print(len(h20))
# output: 4
h2 = Hand.roll(Hand(), size=3)
print(h2)
# output: [17, 12, 10]
I have two questions:
why does it say "cannot get length of hand" when I can print the length? Maybe not the best question, but I am struggling to find what to debug
when I put the input of h2 = Hand.roll(Hand(), size=3), why would I need to specify the class or "self" in the method when I am calling the method on Hand.roll?
Some guidance and insight would be much appreciated :)
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
def __repr__(self):
return str(self.value)
class D20(Die):
def __init__(self):
super().__init__(sides=20)
class Hand(list):
def __init__(self, size=2):
super().__init__()
self.size = size
for _ in range(size):
self.append(D20())
@property
def total(self):
return sum(self)
def roll(self, size):
for item in range(size):
if item+1 > self.size:
self.append(D20())
if item+1 == size and self.size > size:
del self[item]
if item+1 < self.size:
self[item] = D20()
self.size = size
1 Answer
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsHello Johannes Scribante
So I copied your classes, I removed parts of the class to shorten a little so I could add comments into it to explain some of whats going on. First lets start off with understanding the comments. Then if you are still confused we will go from there.
hand.py
class Hand(list):
"""
Answer 1
Since Hand inherits from list python data type
You are given some prebuilt things for free.
One of these things is a method called __len__().
__len__() defines how a list will print the length of itself.
Because not all Objects know how it should count itself or the
data it may contain.
"""
# ... rest of class removed
def roll(self, size):
"""
Answer 2
self is normally passed to methods
inside a class when you need to DO something
with 1 specific instance of that class.
This means the instance HAS to be created before
you can call this method.
Other types like classmethods or staticmethods
do not require self to be passed. And do
not require an instance to be created.
"""
for item in range(size):
if item+1 > self.size:
self.append(D20())
if item+1 == size and self.size > size:
del self[item]
if item+1 < self.size:
self[item] = D20()
self.size = size
dice.py
class Die:
# ... rest of class removed.
def __repr__(self):
"""
Without this method, print any instance
of a die or any instance that inherits from
this Die class would print from the
default Object __repr__ method.
Because all classes in Python 3, by default,
inherit from the object data type.
"""
return str(self.value)
class D20(Die):
"""
Just like Hand inherits all methods from list.
D20 is inheriting all the methods you defined from Die.
With the exception of the __init__ method, because
you have overridden the default inherited one.
"""
def __init__(self):
super().__init__(sides=20)
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsIn your output code, I seen this line.
h2 = Hand.roll(Hand(), size=3)
print("h2: ", h2)
# output: [17, 12, 10]
I copied your code into a Workspace and ran it. I definitely didnt get an output of [17, 12, 10]
But I shouldnt have, I dont know if this was what you were expecting to come back? or an output you accidentally left.
so to explain what is happening in those lines.
# 1. You are telling Python to call the roll method on Hand.
# 2. Then you are telling it to store the returned value from roll into h2 variable.
h2 = Hand.roll(Hand(), size=3)
# Problem: roll needs a self argument (which has to be an instance).
# In first argument, you created a new instance and passed it as that argument.
# But since roll doesnt return anything... you just lost that instance of Hand.
# and h2 will become None.
# You could have roll method return THAT copy of self.
# then h2 would hold that new instance and you wouldnt lose it.
# I probably wouldnt recommend doing this, you could make a classmethod instead.
# But for learning purposes I am telling you how to MAKE your code work.
# So you can play with it some more. :)
Let me know if that makes sense or if you have more questions!
Johannes Scribante
19,175 PointsThanks Chris for the help! The answers you gave weren't quite what I was hoping, usually when we get stuck with a problem we normally just want it solved without too much understanding as long as it works. You however nudged me in the right direction to solve the problem.
Thanks for all the comments! Really helped again just to understand some of the smaller issues like the __repr__
and what self
means in the instances and classes.
One thing I missed was to include the import of the D20() class.
Also here is the sudo code I used to finally solve the code challenge. Hopefully it helps and explains correctly to someone else. I would recommend going back to the video about books and the bookshelf (https://teamtreehouse.com/library/constructicons) this really helped
class Hand(list):
# set __init__ of Hand()
# create new list instance by giving List(dice_in_hand) else default to None
# therefore dice_in_hand should be a list
@property
def total(self):
return sum(self)
@classmethod # call a method on a class, without the class instance yet existing
# pass it a class (itseld Hand) and an argument size_of_hand we want
# initialize an blank list of dice_in_hand
# loop through the size_of_hand we want
# append new instance of D20() to dice_in_hand
# return the newly created instance, when you call the cls, to create a new instance of the class passing it the list of dice_in_hand. I.e. call the __init__ of Hand()
If anyone has some tips on how to comment better, please let me know :)
These code challenges are really helpful to put into practice what we learn!
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsWell I promise that I will never just GIVE the answer. :-)
In programming every problem can have multiple solutions, of those solutions there is generally 1 really good solution for that specific scenario. So just handing out answers doesn't help at all. But if you can teach the concepts and show the person how to figure it out, then they will be better prepared for the next problem they come across to be able to solve it.
I avoid giving answers at all time. Its actually a little irritating when I see other students just copy/pasta their solution code without trying to help them learn first.
Johannes Scribante
19,175 PointsHi Chris, sorry if this feels like spam, I'd rather ask than not. Regarding my comment where I included my code as sudo code, would you say even that is to clear cut and would take away the opportunity from someone else to learn?
I'd be more than happy to remove my code snippet. I thought it may guide someone else in a direction without giving them the answer, I also don't way to push them into thinking that is the way to solve the problem. Like you said there may be other ways to do it and this happened to be mine. I don't know if it's the best but it worked.
Part of the learning process is to struggle until you hopefully understand why you are doing what you do.
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsAs long as you arent giving the direct copy/pasted code should be fine. Pseudo code is generally just your thought process on writing the code. The students still have to derive the coded answer to pass the challenge. So I would say your pseudo code comments are fine.
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsChris Howell
Python Web Development Techdegree Graduate 49,702 PointsEdit: Fixed the first code snippet to use markdown as well. :)