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

Duy Pham
PLUS
Duy Pham
Courses Plus Student 44,614 Points

I really need help on this question to move on. Please help

Alright! Now I need you to add a new property called doubles. It should return True if both of the dice have the same value. Otherwise, return False.

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 CapitalismHand(Hand):
    def __init__(self, *args, **kwargs):
        super().__init__(size=2, 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)
        }

3 Answers

Hi, Duy

The [underscore]sets property returns a dictionary, and the values of this dictionary are the number of times a 1 or 2 or 3 or 4 or 5 or 6 was rolled. So if you have a CapitalismHand instance that rolls 2 six-sided dice, and one dice gives you a 5 and the other dice gives you a 6, then the [underscore]sets property on that instance would return the dictionary "1: 0, 2: 0, 3: 0, 4: 0, 5: 1, 6: 1".... but if you rolled doubles instead, then you would have gotten two 6's or two 5's or two 4's, etc. So, here's one way to solve this using the dictionary's "values" method.

    @property
    def doubles(self):
        for num in self._sets.values():
            if num > 1:
                return True
        return False     # if the "for" loop never returns True (thereby exiting the method) then the method returns False.
Duy Pham
Duy Pham
Courses Plus Student 44,614 Points

Thank you so much ds1. You showed what need to be done with a great explaination and that's exactly what i need. Thanks again. I really appreciated

Chris Freeman
Chris Freeman
Treehouse Moderator 68,453 Points

There is a short cut solution to Task 2. Since the class inherits from list class, it's members can be accessed directly. "Doubles" can be checked using self[0].value == self[1].value or even simpler: self[0] == self[1]

Musashi Schroeder
Musashi Schroeder
4,289 Points

Ended up with something like Chris Freeman :

@property
    def doubles(self):
        if self[0] == self[1]:
            return True
        else:
            return False

Chris Freeman , can you tell me why set() does not work here:

    @property
    def doubles(self):
       if (len(set(self))==1):        
             return True
        else:
            return False

in the previous code challenge this code is fine:

    def score_yatzy(self, hand):
        if (len(set(hand))==1):
            return 50
        else:
            return 0    

is it related to @property vs a normal function?

Chris Freeman
Chris Freeman
Treehouse Moderator 68,453 Points

It is not whether it is a property or not. The challenges appear to use different inputs. In yatzy_scoring, the hand input for the self appears to be a simple list of ints. In the CapitalismHand, self is a list of D6 instances.

For set to operate on an object, the object needs to be hashable, that is, it has defined both __hash__ and __eq__ methods.

Without these two methods, set will simply compare the object reference ids which is guaranteed to be unique. Defining a __repr__ method would allow a cleaner view of what is being compared, but without the __hash__ and __eq__ methods, no actual comparison is being made.

>>> ch = CapitalismHand()
>>> ch
in CH.__repr__
in Hand.__repr__
[<__main__.D6 object at 0x7fc75176cef0>, <__main__.D6 object at 0x7fc75176ce80>]

# Add yatzy method and call
    def yatzy(self):
        print("in Hand.__yatzy__")
        if (len(set(self))==1):        
            return True
        else:
            return False

>>> ch, ch.yatzy()
in Hand.__yatzy__
in CH.__repr__
in Hand.__repr__
([<__main__.D6 object at 0x7fc7517854e0>, <__main__.D6 object at 0x7fc7517857f0>],
 False)

# add Die.__repr__ method
    def __repr__(self):
        print("in Die.__repr__")
        return str(int(self))

>>> ch, ch.yatzy() 
in Hand.__yatzy__
in CH.__repr__
in Hand.__repr__
in Die.__repr__
in Die.__repr__

([4, 4], False)  # yatzy still False

# Add __hash__ and __eq__
    def __hash__(self):
        print("in Die.__hash__")
        return int(self)

    def __eq__(self, other):
        print("in Die.__eq__")
        return self.value == other

>>> ch, ch.yatzy() 
in Hand.__yatzy__
in Die.__hash__
in Die.__hash__
in Die.__eq__
in Die.__eq__
in CH.__repr__
in Hand.__repr__
in Die.__repr__
in Die.__repr__
([5, 5], True)    

Post back if you wish more help. Good luck!!

You're very much welcome!! : )