First things first: your code reads nowhere near Python code. You should read into PEP8 to properly format it.
Second, you should strive to avoid global
as hard as you can as it easily make the code error-prone, hard to reason about, and hard to test. In your case, of the two global variables you use, stopMessage
is read-only so it is much like a constant where the use of global
is unnecessary. The second one, statsMax
is trickier. For your simple use-case, it seems to work, but if you were to create a second player, statsMax
would be 0 and it would be impossible. Instead, you should make it a parameter of some sort: the __init__
method of the stats
class seems a good starting point:
class stats(statsStore):
def __init__(self, max_points=26):
...
self.max_points = max_points
There is also the fragmentation of the source code into two files. Even though it is good to consider at some point to be able to group related functionnalities under a namespace, you have too few functionnalities for it to be usefull. It even lead to the duplication of the stopMessage
. Keep it simple for now with a single file.
The design of the stats
class is also very fragile: the statsFunc
method is not meant to be called outside of statsList
and statsList
itself have to be called for the stats
object to be considered initialized. This is the role of a simple function, maybe a classmethod
on the statsStore
class itself. Moreover, statsStore
is only there to be a collection of values: better use a namedtuple
here.
One more thing that intrigues me is how you use some parameters. For instance stat
in statsFunc
or Check
in checkIn_List
. It is like you want to declare a variable before use, but you never do anything with the value passed as parameter. You don't need that. Just assign a value to a new name whenever you need a new variable, and don't pass unnecessary parameters around.
Lastly, instead of putting tests at the end of the file, you should wrap them under an if __name__ == '__main__'
test so they don't get executed when you import
your file (in a Python shell to test it, or in an other module).
Proposed improvements:
import sys
from collections import namedtuple
Statistics = namedtuple('Statistics', 'strength, perception, endurance, charisma, intelligence, agility, luck')
def ask_for_value_in_list(prompt_message, *authorized_values):
while True:
value = input(prompt_message)
word = ''.join(filter(str.isalpha, value)).lower()
if word in authorized_values:
return word
if word == 'exit':
raise ValueError('asked to exit')
print('Only one of the following values is allowed:', authorized_values, file=sys.stderr)
def ask_for_integer(prompt_message):
while True:
value = input(prompt_message)
try:
return int(value)
except ValueError:
if value.lower() == 'stop':
raise
print('An integer is required!', file=sys.stderr)
def ask_for_stats(stat_name, max_points):
message = '[{} points left] {} >>> '.format(max_points, stat_name)
while True:
value = ask_for_integer(message)
if 1 <= value <= max_points:
return value
print('The provided value is out of bounds, try again.')
def build_statistics(max_points=26):
statistics = dict.fromkeys(Statistics._fields)
for statistic in statistics:
if not max_points:
raise ValueError('character exhausted statistics points')
value = ask_for_stats(statistic, max_points)
max_points -= value
statistics[statistic] = value
return Statistics(**statistics)
def main():
try:
stats = build_statistics()
except ValueError:
print('Could not build statistics, aborting.', file=sys.stderr)
else:
print('Statistics collected:', stats)
if __name__ == '__main__':
main()
I didn't put back the check for the strength being at least 10 points, but it should be easy enough to add it back if you really need it.