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

Trying to run code at end of 'Yatzy Scoring'...

Please help!

Trying to run code at end of 'Yatzy Scoring', but getting AttributeError: 'YatzyHand' object has no attribute '_by_value

from copy_1 import D6

class Hand(list):
    '''Provide number(8) and type(die_class) of dice to roll
    ...then use these to append dice to our list
    die_class = Add arg to hold class that all Dice will be'''
    def __init__(self, size=8, die_class=None, *args, **kwargs):

        '''If no die_class provided...'''
        if not die_class:
            raise ValueError("\n\n*****\nPlease provide a die_class\n*****")
        super().__init__()

        ''' Pluggable requirement to load list with a num of 
        die_class objects'''
        for _ in range(size):
            self.append(die_class())

        '''Call sorting method'''
        self.sort()

        '''Add utility that returns all dice with a certain value
            Best used in subclasses in 'larger than one hand' app'''
        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 for each hand of one value '''
    @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)

    ''' Return map where keys = die value, value = how many of 
    that value are in each hand'''
    @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)}


class YatzyScoresheet:
    ''' Ones '''
    def score_ones(self, hand):
        return sum(hand.ones)
    ''' Twos '''
    ''' Threes'''
    ''' etc.'''

    ''' Method to score dice by num items in a set '''
    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)

    ''' Method scores a single pair, i.e., 2 items from hand'''
    def score_one_pair(self, hand):
        return self._score_set(hand, 2)


hand = YatzyHand()
three = D6(value=3)
four = D6(value=4)
one = D6(value=1)
hand[:] = [one, three, three, four, four]
print(YatzyScoresheet().score_one_pair(hand))

3 Answers

def _by_value(self, value):

is indented too far. It should be at the same level as:

def __init__(self, size=8, die_class=None, *args, **kwargs):

Good catch, Chris.

Since your catch was on my attempt in workspaces, I still gotta give best answer to Kris since that was my original attempt :P

Okay, got a snapshot: https://w.trhou.se/ijj8js9e1s

I tried to set it up exactly like in the video. I ran it again and got this result:

>>> hand = YatzyHand()                                                                                                         
>>> three = D6(value=3)                                                                                                        
>>> four = D6(value=4)                                                                                                         
>>> one = D6(value=1)                                                                                                          
>>> hand[:] = [one, three, three, four, four]                                                                                  
>>> YatzyScoresheet.score_one_pair(hand)                                                                                       
Traceback (most recent call last):                                                                                             
  File "<stdin>", line 1, in <module>                                                                                          
TypeError: score_one_pair() missing 1 required positional argument: 'hand'                                                     
Chris Freeman
Chris Freeman
Treehouse Moderator 68,468 Points

This difference in this result is due to the missing parentheses after YatzyScoresheet. Without the parentheses you are referencing in unbound message directly, So hand is being assigned to self and nothing is being assigned to hand.