Bummer! You must be logged in to access this page.

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

Python

AttributeError 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

Hi 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:

hands.py
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!

Hello 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!

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)

        @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)