Repeatedly multiplying digits until a single digit is obtained I've written code that solves a problem from codewars.com. My code passes all the tests on the codewars site. It's a simple enough problem to solve naïvely, but I would love to improve the structure.

The prompt for the problem is as follows:


  Write a function, persistence, that takes in a positive parameter num
  and returns its multiplicative persistence, which is the number of
  times you must multiply the digits in num until you reach a single
  digit.
  
  For example:

persistence(39) =&gt; 3  # Because 3*9 = 27, 2*7 = 14, 1*4=4
                      # and 4 has only one digit.



So my solution follows:

def get_digits(num, digits=[]):
    while num &gt; 0:
        digits.append(num % 10)
        return get_digits(num / 10, digits)
    if num == 0:
        return digits


def multiply_all(digits, multiplier=1):
    while len(digits) &gt; 0:
        multiplier = multiplier * digits.pop(0)
        return multiply_all(digits, multiplier)
    if len(digits) == 0:
        return multiplier


def persistence(num, count=0):
    while num &gt;= 10:
        num = multiply_all(get_digits(num))
        count += 1
        return persistence(num, count)
    if num &lt; 10:
        return count


I was thinking I might consolidate these three little recursive functions into one function containing all three... but I'd really like input from more seasoned programmers, so I very much appreciate you taking the time to make any suggestions.
Python 3.x bug

Did you know that your program outputs 1 for the number 39 if executed on Python 3?

This is because of the / division operator on this line:

return get_digits(num / 10, digits)


The meaning of / in Python 3.x was changed (PEP 238). Switching to // would be a quick fix.



Improving the solution


  I was thinking I might consolidate these three little recursive
  functions into one function containing all three..


What if we would get all the digits of a number by iterating over the string representation of an integer and converting every digit back to an integer - map(int, str(num)). In order to multiple the digits of a number we can use reduce() applying the operator.mul (multiplication operator) function:

from functools import reduce
from operator import mul


def persistence(number, count=0):
    # recursion base case - exit once the number is less than 10
    if number &lt; 10:
        return count

    # get new number by multiplying digits of a number
    new_number = reduce(mul, map(int, str(number)))

    return persistence(new_number, count + 1)


Note that you don't actually need the while loop at all, since you are going recursive and have a num &lt; 10 base case as a recursion "exit condition".



Note that you can also approach the "getting digits of a number" "mathematically" instead of converting the types back and forth:

from functools import reduce
from operator import mul


def get_digits(number):
    """Generates digits of a number."""
    while number:
        digit = number % 10

        yield digit

        # remove last digit from number (as integer)
        number //= 10


def persistence(number, count=0):
    if number &lt; 10:
        return count

    # get new number by multiplying digits of a number
    new_number = reduce(mul, get_digits(number))

    return persistence(new_number, count + 1)


This would also be generally faster than the first version.