I have some observations that are mostly language-independent.
Document your functions
A clear description of functionality helps when you're considering re-using code in a new project. Get in the habit of writing good doc-comments early, so you're not caught out trying to unravel your logic when it matters!
Accept command-line arguments
It's tedious to test a program if you always need to supply inputs. Simple numbers are best provided as arguments when invoking the program (consider reading from the input stream as a fallback).
Does it make sense to accept negative numbers? I don't think so; we should refuse to operate if any of the inputs are zero or less.
Separate computation and I/O
It's hard to unit-test code that produces output using
print(). It's easier if we return an collection of values or if we write to a supplied iterator. Python helps us, because it allows us to write a generator simply by using
yield to return each value.
Division is the most expensive of the basic arithmetic operations
getString() (which should be
get_string() by PEP-8, but really needs to be something more informative) has no knowledge that it is being called with sequential values of
num. That prevents a key optimisation that's possible if we inline the function. Then we're able to maintain variables to record the remainders without needing the
Incorporating my suggestions, and some improvements from other answers:
def fizzbuzz(max_num, fizz, buzz):
A generator that transforms the range [1..max_num], returning each
number converted to string, unless it's an exact multiple of
'fizz' (when it returns the string "Fizz") or of 'buzz' (returns
"Buzz") - or for multiples of both divisors, the combined string "FizzBuzz".
>>> list(fizzbuzz(6, 2, 3))
['1', 'Fizz', 'Buzz', 'Fizz', '5', 'FizzBuzz']
>>> list(fizzbuzz(6, 2, 4))
['1', 'Fizz', '3', 'FizzBuzz', '5', 'Fizz']
# accumulators tracking num % fizz and num % buzz
fizz_acc = 0
buzz_acc = 0
for num in range(1, max_num + 1):
fizz_acc += 1
buzz_acc += 1
result = ""
if fizz_acc == fizz:
fizz_acc = 0
result += "Fizz"
if buzz_acc == buzz:
buzz_acc = 0
result += "Buzz"
yield result if result else str(num)
def arg_or_input(argno, prompt):
Read a value from the 'argno'th command-line argument,
or if there are fewer, use 'prompt' to input interactively.
if __name__ == '__main__':
fizz = int(arg_or_input(1, "Enter the number to Fizz: "))
buzz = int(arg_or_input(2, "Enter the number to Buzz: "))
max_num = int(arg_or_input(3, "Enter the maximum number: "))
print("Inputs must be integers!", file=sys.stderr)
if fizz <= 0 or buzz <= 0 or max_num <= 0:
print("All inputs must be positive!", file=sys.stderr)
for s in fizzbuzz(max_num, fizz, buzz):