Python Object-Oriented Python Dice Roller RPG Roller

Guy Larkin
Guy Larkin
1,662 Points

RPG Roller code not working - is the same as others who say their code passed...

In hands.py, when I check my work, I get the message: Bummer: Couldn't import 'Hand'.

I looked on the boards, and this code is exactly the same as another student's who said it passed. I even changed some of my argument names to match, just in case that was the issue. Can anyone let me know what I am doing incorrectly here? Thanks!

dice.py
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


class D20(Die):
    def __init__(self):
        super().__init__(sides=20)
hands.py
import dice

#update Hand
#code such as Hand.roll(2) will get back an instance of Hand with 2 D20s rolled in it
#then .total should be callable on the instance to get a total of the two dice

class Hand(list):
    def __init__(self, size=0, die_class=D20):
        super().__init__()
        for _ in range(size):
            self.append(die_class())


    @classmethod
    def roll(cls, size):
        return cls(size,  die_class=D20)


    @property
    def total(self):
        return sum(self)

2 Answers

Louise St. Germain
MOD
Louise St. Germain
Treehouse Moderator 12,228 Points

Hello Guy,

You're nearly there! (And thankfully, the fix is easy!) The reason the code isn't quite working is that there's a mismatch between the way dice was imported, and the way it's being referenced in the code.

There are two ways to import (well, more than two, but two important ones that I'll discuss here): one is to import a whole module (basically, a file - same name as file but minus the .py extension), and one is to import a class from within a module/file.

# Import the entire module (in this case, dice.py)
import dice

# Import a class from a module
from dice import D20

When a whole module is imported, as in your original code (import dice), Python creates a reference (think of it as a link) to the module as a whole, but not to all the individual bits and pieces inside it. So if you're in a different file (as is the case here), and you want to reference a class or some other stuff inside the module you imported, you need to use a 2-part notation, like dice.D20(). That way, Python knows to go into the dice file (which it has a reference to), and you can then point it to D20 from there. If you just write D20(), it doesn't know what to do with that since it hasn't recorded the fact that D20 is inside dice.

If you go with the second option and do:

from dice import D20

Python has now directly created a link specifically to D20 inside your other file, and you can now use short references (without the module name), like D20() instead of dice.D20().

So to fix your code, there are 2 options:

  1. Switch the import statement to "from dice import D20". Then you can leave the rest of the code as is.

or,

  1. Keep the import statement as "import dice", but then wherever you see "D20" inside hands.py, you'll need to change it to "dice.D20", for example:
class Hand(list):
    def __init__(self, size=0, die_class=dice.D20):
# instead of die_class=D20
# You have this twice in your code so you'd need to change it in both places

I hope this helps! Let me know if you still need any clarifications.

Guy Larkin
Guy Larkin
1,662 Points

Thank you! Now that you've said it, I'm face-palming.

Louise St. Germain
MOD
Louise St. Germain
Treehouse Moderator 12,228 Points

You're welcome! Yeah, I know I've also spent countless hours trying to figure out problems that turn out to be something trivial in the end! :-)