Below I've answered the question about a better way to write the replacement, but I've also re-written your code in some other ways that I will explain below how and why I changed it the way I did.
Starting with def write_log(name, total):
it would be better to use a more meaningful variable name, num
, since you expect a number which you'll later be converting into a name
.
It is good that you used total = int(total)
to make sure that the input is, indeed, a number. We'll do that with the new variable num
, as well. Note, that if this fails it will throw a ValueError
exception.
Next, since you have a list of names, make them explicitly a list with ['triangle','square'...]
. Here I also give it a meaningful variable name, shapes
.
For the replacements, this is a good candidate for using a dict
ionary data structure. And since you want to number each of these names in order you can use the enumerate
function; note that by default it will start the numbering from 0, but since you want to start from 1 in your example, I added the starting number as the second argument to enumerate
.
Once you have enumerated your shapes list into a dictionary you can now use num
as a key to get the value (the shape name). I wrapped it in a try ... except
block in case someone called write_log
with an invalid value. If an exception happens, then we print an error to stderr
and then return
from the function. I used this exception handling as an example to show when you would want to use return
; in this case we are returning from the middle of the function. Note that I removed the return at the end of your program because you don't have to explicitly write return
at the end unless you are actually returning some value, but in your example your function returns nothing at the end, so there is no need to write it out explicitly there at the end.
For pluralization we can simplify further by separating out the pluralization from the log message itself. We only append an 's'
if total
is greater than 1; I'm not sure when you had total <= 5
, but if you really only wanted pluralization for >=2 and <=5
, then you could write it that way, but >1
seems to make more sense here. Then building the string for the log message is the same whether or not name is plural.
To open the log file it is better to use the with
statement. That will put a try ... finally
block around the code so that the file is automatically closed once the logfile variable is no longer in scope (including if an exception is thrown). What you wrote here is definitely correct (and good practice), but since it is such a common pattern the with
statement was created for exactly this purpose (see PEP 343).
#!/usr/bin/env python
import sys
def write_log(num, total):
# ensure that inputs are numbers
num = int(num)
total = int(total)
shapes = ['triangle', 'square', 'rectangle', 'pentagon', 'hexagon', 'octagon', 'circle']
replacements = dict(enumerate(shapes, 1))
try:
name = replacements[num]
except KeyError:
sys.stderr.write('Error: %i is not a valid input.\n' % (num))
return
if total > 1:
name += 's' # add s to name to make it plural
with open('text.txt', 'a') as logfile:
msg = '%i %s \n' % (total, name)
logfile.write(msg)
def main():
write_log(1, 2)
write_log(23, 5) # this will generate an error
write_log(3, 4)
if __name__ == "__main__":
main()