To my eye the code looks functional. With some issues. Let’s look at it:
class Die():
"""Represent a die which can be rolled."""
Looks fine. This introduces a Die class (with no superclasses other than
the implicit “object” superclass). Classes with no superclasses can just
be defined like this: class Die:
, omitting the brackets.
I case it isn’t clear, a class does 2 primary things: each instance of
the class keeps some state (in you case, the number of sides to the die)
and provides some methods to do things with the instance from outside,
which do not need to caller to know the internals of how the class does
them. For example, roll_die() works and returns a number without the
caller knowing how the instance does that, or even how it knows how many
sides there are on the die.
def __init__(self, sides=6):
"""
inititialize the die.
"""
self.sides = sides
Also fine. Sets the internal state of a new instance, by saving the
number of sides, with a default of 6.
def roll_die(self):
"""Return a number from 1 to the number of sides."""
return randint(1, self.sides)
for roll_num in range(10):
result = six.roll_die()
print(result)
This is also fine, up to the return. it computes a (pseudo)random number
using randint() and returns that number.
However, this method also contains a for-loop which looks like it
leaked in from the other code. That loop would have tried to call the
method again. In practice: (a) the loop never runs, because of the
“return” statement above it and (b) it would fail “six”, if defined by
the time this method is called, would just call itself forever (because
six.roll_die() would call six.roll() die, which would call
six.roll_die(), which…).
The blank line you had between the “return” statement and the for-loop
does not end the method. The indentation says that the for-loop is part
of the method.
six = Die()
six.roll_die()
This is also fine. It creates a new instance of “Die” and associates it
with the variable “six”. The you call the instance’s roll_die() method,
which computes a new random value. However, you do not store that value
anywhere or print it, so you do not see the effect of calling the
method. The method is called, but the method is silent (can you imagine
the noise if every method printed stuff out?)
By changing the last line to:
print("roll =", six.roll_die())
you will see the value returned. You could equally store the value:
roll1 = six.roll_die()
or call it sevaral times and store (or print, or whatever) all the
values.
If you do not know if the method is getting called (a not uncommon
debugging situation) you can stick a print() in the method itself:
def roll_die(self):
"""Return a number from 1 to the number of sides."""
roll = randint(1, self.sides)
print(f"{self}.roll_die =>", roll)
return roll
Notice that we store the value in a variabe (a variable local to the
method - it does not leak to the caller of the method). This is because
we want to do 2 things: print it and return it. So we compute “roll”.
Then print. Then return.
Cheers,
Cameron Simpson cs@cskk.id.au