Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](httphttps://codereview.stackexchange.com/q/111337/78136) or [here](https://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](https://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](https://codereview.stackexchange.com/q/111337/78136) or [here](https://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](httphttps://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](http://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](https://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
In general your code looks nice, but it does show that you've got a another programming language background, and thuslythus you do it the standard imperative way instead of utilizing some of the more pythonic way. In this review I'm deliberately going a little over the top, but in return you get to see some of the more special pythonic constructions.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e. """ ... """""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thingything is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](http://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
In general your code looks nice, but it does show that you've got a another programming language background, and thusly you do it the standard imperative way instead of utilizing some of the more pythonic way. In this review I'm deliberately going a little over the top, but in return you get to see some of the more special pythonic constructions.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e. """ ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thingy is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](http://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.
In general your code looks nice, but it does show that you've got a another programming language background, and thus you do it the standard imperative way instead of utilizing some of the more pythonic way. In this review I'm deliberately going a little over the top, but in return you get to see some of the more special pythonic constructions.
Using
__doc__to get the docstring fordisplay_help– In Python you can and should describe your code using docstrings, typically text with triple quotes, i.e.""" ... """. These can be used to describe the module, functions, classes (and methods). They typically come on the line after the definition of the item you want to document.A neat thing is that this docstring can be accessed using a special variable,
__doc__, or for a function asdisplay_help.__doc__. And then it can be used for print outs, or similar.Work a little more on naming methods – It is not very common in Python to have
get_xxxxmethods, rather name them according to specific function, likeroll_multiple_dice()orroll_die(). Aim for simplicity and clarity. Usingget_answer()implies that you want me to insert the answer of something, whilstnumber_of_pythons()indicates that this is going to be calculated.List comprehensions are your friend – Instead of repeating code to build the list, use
return [roll_die() for _ in range(number_of_dice)]which implements three nice features:- A list comprehension, which builds a list based on the inner generator, i.e.
[ ... ] - The use of
forwithin the generator,x for x in range(y), which compresses aforloop into the expression. This one would return the numbers from0toy-1 - The use of
_when we don't really care about the number, but just want the code in front of theforloop to be executed
- A list comprehension, which builds a list based on the inner generator, i.e.
Generator expressions – The
forloop of last item, can also be used outside of list comprehension, i.esum(x for x in range(y)), which would sum all the numbers from0throughy-1.One major difference between a list comprehension and generator, is that the list comprehension actually builds the entire list, whilst the generators works in the background and gives you another element when you want it.
In the sum example this means that if you had
y=1000000you wouldn't allocate memory for more than 1 int, whilst if you used list comprehension you would allocate the entire list of 1 million elements, and then sum it.The Python ternary, i.e.
a = b if c else d– This could take some time to get used to, but actually it reads out quite nicely: Set the value ofatobif the conditioncis true, ordif not true.Disclaimer: In my refactored code this is where it got a little ugly, as I combined multiple of this construction. But still, they kind of make sense. I used them in both
number_of_pythons()andprint_dice().Avoid one-time intermediate variable – It's quite common to skip the intermediate variable, especially if you use them only once, and rather use the expression directly. I.e. in
roll_die()just return the random number, and inroll_multiple_dice()return the list directly.In some cases, you can sum using Booleans – Doing the
if True: a += 1is kind of an anti-pattern, and can in some cases be replaced bya += True, or in your case:streak += play_once(...).- Bug found by 200_success: Here the simplification went too far, as I by simply summing, removed the resetting of the streak counter.
Avoid flag variables, if possible – Your use of
validinget_guess()is better written usingwhile Trueand abreaklike in your input validations. And skipping the intermediate variable, you could return straight out of the loop.Try to avoid the chained
ifcommands, doing the same stuff – In bothget_answer()andprint_dice()you haveifchains where the block kind of does the same. This is usually an indication that you could find a better way of handling it.In
get_answer()I opted for a double ternary, doinganswer += 2 if i == 3 else 4 if i == 5 else 0.In
print_dice()I used the fact that a six sided die has only 5 distinct patterns, and then I used yet another double ternary to select from the different options._Disclaimer:_ Even though this code is a lot shorter than yours, that doesn't mean it is nicer as such. But it does show an alternate way, and there are multiple ways to print die results. See [here](http://codereview.stackexchange.com/q/111337/78136) or [here](http://codegolf.stackexchange.com/a/2603/45969).
Use constants, not magic number – Instead of hiding a
5and an8in the code, use constants at top of file likeREQUIRED_STREAK_RUN = 8andNUMBER_OF_DICE = 5. This allows you to change them easily (and you can still make the document reflect the change usingstr.format()Use str.format() for string formatting - This is a very useful construct, which is well worth some time to look into. You could either use it without names (see end of
play_once()), or you could name your variables like indisplay_help().PS! If using Python 2, I recommend using
from __future__ import print_functionto get the full extent of this beauty there as well.Feature: You can't quit your program without becoming a Pythentate – I think it's nice to give users a way out. I've implemented a lazy version with terminating if entering a negative answer. This could be done a lot nicer, but it should be an option to quit at any time.