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 trial
J R
Courses Plus Student 12,168 PointsAttributeError when running program
After following along with the video when I run the command that Kenneth does at 7:24 in the video, "YatzyScoresheet().score_one_pair(hand)" I receive the following error.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/treehouse/workspace/yatzy/scoresheets.py", line 13, in score_one_pair
return self._score_set(hand, 2)
File "/home/treehouse/workspace/yatzy/scoresheets.py", line 7, in _score_set
for worth, count in hand._sets.items():
AttributeError: 'YatzyHand' object has no attribute '_sets'
MOD: I just added some formatting to the console output so it's a bit easier to read.
2 Answers
Louise St. Germain
19,425 PointsHi Jai,
Thanks for posting the code! One thing to fix for sure is that all the properties inside YatzyHand are indented too far. i.e., they should not be inside that def __init__. So you'll need to grab all those properties and unindent them a level. The same goes for that def _by_value in the Hand class: it should not be embedded inside the def __init__ block. So you'll need to grab that block and unindent that also.
The code should look like this once you make the changes:
from dice import D6
class Hand(list):
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 _by_value(self, value):
dice = []
for die in self:
if die == value:
dice.append(die)
return dice
class YatzyHand(Hand):
def __init__(self, *args, **kwargs):
super().__init__(size = 5, die_class = D6, *args, **kwargs)
# Properties at same indentation level as def.
@property
def ones(self):
return self._by_value(1)
@property
def twos(self):
return self._by_value(2)
@property
def threes(self):
return self._by_value(3)
@property
def fours(self):
return self._by_value(4)
@property
def fives(self):
return self._by_value(5)
@property
def sixes(self):
return self._by_value(6)
@property
def _sets(self):
return {
1: len(self.ones),
2: len(self.twos),
3: len(self.threes),
4: len(self.fours),
5: len(self.fives),
6: len(self.sixes)
}
Another thing to watch out for is mixing spaces and tabs for indentation. This might be OK here, but could certainly cause problems in other places if you happen to mix both in one file. scoresheets.py is indented with tabs, and hands.py is indented with spaces. It would be a good idea to make sure everything is consistent, and indent both files only with spaces (that should be the default in whatever editor you use for Python).
Anyway, try fixing the indentation per above and see if it works any better - let me know how it goes!
Louise St. Germain
19,425 PointsHello Jai,
Check your hands.py file that goes with this, and specifically check that you've typed the property name correctly there (with the underscore before sets, and sets being plural). You should have this block somewhere inside the YatzyHand class definition (assuming I'm thinking of the correct exercise!):
@property
def _sets(self):
return {
1: len(self.ones),
2: len(self.twos),
3: len(self.threes),
4: len(self.fours),
5: len(self.fives),
6: len(self.sixes)
}
If there are no typos in your property name, could you post your code for both hands.py and scoresheets.py? It will be easier to debug if we can see the actual code that's causing problems. Thanks!
J R
Courses Plus Student 12,168 Pointsfrom dice import D6
class Hand(list):
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 _by_value(self, value):
dice = []
for die in self:
if die == value:
dice.append(die)
return dice
class YatzyHand(Hand):
def __init__(self, *args, **kwargs):
super().__init__(size = 5, die_class = D6, *args, **kwargs)
@property
def ones(self):
return self._by_value(1)
@property
def twos(self):
return self._by_value(2)
@property
def threes(self):
return self._by_value(3)
@property
def fours(self):
return self._by_value(4)
@property
def fives(self):
return self._by_value(5)
@property
def sixes(self):
return self._by_value(6)
@property
def _sets(self):
return {
1: len(self.ones),
2: len(self.twos),
3: len(self.threes),
4: len(self.fours),
5: len(self.fives),
6: len(self.sixes)
}
Here is scoresheets.py
class YatzyScoresheet:
def score_ones(self, hand):
return sum(hand.ones)
def _score_set(self, hand, set_size):
scores = [0]
for worth, count in hand._sets.items():
if count == set_size:
scores.append(worth*set_size)
return max(scores)
def score_one_pair(self, hand):
return self._score_set(hand, 2)