Numbers
"""
translate - translates number words to digits
Example Usage:
.. code-block:: bash
$ translate.py one two three
123
$ translate.py zero zero five zero six zero
5060
$ translate.py blah two blah four
2 4
Any leading "zero" arguments are ignored.
Invalid digit words are converted to spaces.
"""
import sys
def translate_numbers(*number_strings):
numbers = []
for item in zip(range(len(number_strings)), number_strings):
i,n = item
if n == "zero":
if i != 0:
numbers.append(0)
elif n == "one":
numbers.append(1)
elif n == "two":
numbers.append(2)
elif n == "three":
numbers.append(3)
elif n == "four":
numbers.append(4)
elif n == "five":
numbers.append(5)
elif n == "six":
numbers.append(6)
elif n == "seven":
numbers.append(7)
elif n == "eight":
numbers.append(8)
elif n == "nine":
numbers.append(9)
else:
numbers.append(' ')
return numbers
def main(numbers):
number_list = numbers
numbers = translate_numbers(*number_list)
numbers = map(str, numbers)
print("".join(numbers))
if __name__ == "__main__":
main(sys.argv[1:])
Let’s tackle the main function first:
Remove unnecessary
number_listvariable by combining first two lines: “Simple is better than complex.”Use more clear variable name instead of re-using old variable name: PEP 8 and “Readability counts.”
def main(numbers):
translation = map(str, translate_numbers(*numbers))
print("".join(translation))
Remove unnecessary translation variable: “Beautiful is better than ugly.”
def main(numbers):
print("".join(map(str, translate_numbers(*numbers))))
Now let’s work on translate_numbers:
Use
enumerate: “Complex is better than complicated.”Do item unpacking right in for loop: “Simple is better than complex.”
Do append one-time only: “Simple is better than complex.” and “Readability counts.”
def translate_numbers(*number_strings):
numbers = []
for i, n in enumerate(number_strings):
x = None
if n == "zero":
if i != 0:
x = 0
elif n == "one":
x = 1
elif n == "two":
x = 2
elif n == "three":
x = 3
elif n == "four":
x = 4
elif n == "five":
x = 5
elif n == "six":
x = 6
elif n == "seven":
x = 7
elif n == "eight":
x = 8
elif n == "nine":
x = 9
else:
x = ' '
if x is not None:
numbers.append(x)
return numbers
Put string to number translations in dictionary: “Explicit is better than implicit.”
Collapse most of the logic to a dictionary item lookup, catching key errors: PEP 8 and “Errors should never pass silently.”
Use double quotes more consistently: PEP 8 and “Readability counts.”
def translate_numbers(*number_strings):
translation = {
"one": 1,
"two": 2,
"three": 3,
"four": 4,
"five": 5,
"six": 6,
"seven": 7,
"eight": 8,
"nine": 9,
}
numbers = []
for i, n in enumerate(number_strings):
x = None
if n == "zero":
if i != 0:
x = 0
else:
try:
x = translation[n]
except KeyError:
x = " "
if x is not None:
numbers.append(x)
return numbers
Add zero to
translationdictionary: “Explicit is better than implicit.” and “Flat is better than nested.”Invert nested-if special case and move
x = Noneinside if statement: “Complex is better than complicated.”Use dictionary’s
getmethod to use a default on key errors: “Explicit is better than implicit.”Use single quotes for dictionary key strings (personal preference)
def translate_numbers(*number_strings):
translation = {
'zero': 0,
'one': 1,
'two': 2,
'three': 3,
'four': 4,
'five': 5,
'six': 6,
'seven': 7,
'eight': 8,
'nine': 9,
}
numbers = []
for i, n in enumerate(number_strings):
if n == "zero" and i == 0:
x = None
else:
x = translation.get(n, " ")
if x is not None:
numbers.append(x)
return numbers
Invert zero special case logic entirely and collapse if and else: “Simple is better than complex.”
Remove last
x is Nonecheck and just do append all at once: “Simple is better than complex.”Remove unnecessary
xand just append immediately: “Beautiful is better than ugly.”
def translate_numbers(*number_strings):
translation = {
'zero': 0,
'one': 1,
'two': 2,
'three': 3,
'four': 4,
'five': 5,
'six': 6,
'seven': 7,
'eight': 8,
'nine': 9,
}
numbers = []
for i, n in enumerate(number_strings):
if not (n == "zero" and i == 0):
numbers.append(translation.get(n, " "))
return numbers
Move
translationinto global variable (capitalized to denote constant): PEP 8Convert for loop into a list comprehension: “Complex is better than complicated.”
Remove unnecessary
numbersvariable which is returned immediately: “Beautiful is better than ugly.”Use DeMorgan’s law to flip boolean logic in condition: “Simple is better than complex.”
NUMBERS = {
'zero': 0,
'one': 1,
'two': 2,
'three': 3,
'four': 4,
'five': 5,
'six': 6,
'seven': 7,
'eight': 8,
'nine': 9,
}
def translate_numbers(*number_strings):
return [
NUMBERS.get(n, " ")
for i, n in enumerate(number_strings)
if i != 0 or n != "zero"
]