有两个函数可以无休止地运行吗?

时间:2014-12-19 23:31:25

标签: python function python-2.7

我构建了一个简单的Python程序来查找输入是否为2的幂。我有两个功能,power_of_twoplay_again。运行power_of_two后,play_again会运行并重新运行power_of_two

这是我的代码:

num = int(raw_input('Input a number (type 0 to quit): '))
def power_of_two(x):
    y=1
    z=[]
    while y < x:
        y=y*2
        z.append(y)
    if x in z or x == 1:
        print 'true'
    elif x == 0:
        quit()
    else: 
        print 'false'
    play_again()

def play_again():
    num = int(raw_input('Input a number: '))
    power_of_two(num)

power_of_two(num)

Python程序员可以接受这样的代码,还是有更好的方法来复制我在这里做的事情?

3 个答案:

答案 0 :(得分:11)

这种方法的一个问题是你最终会用完堆栈,因为我们有一对相互递归的函数。每次调用都会占用堆栈中的内存,而这些内存永远无法恢复。

这对于交互式程序来说并不明显,因为创建足够的递归调用需要很长时间,但如果我们加快速度:

def power_of_two(x):
    print(str(x))
    play_again(x)

def play_again(x):
    power_of_two(x+1)

power_of_two(1)

我们得到:

RuntimeError: maximum recursion depth exceeded while calling a Python object

有些语言可以进行尾调用优化,所以这种方法运行正常 - 但在Python中最好创建一个循环再次播放&#34;除非你能确定只有是一个小的呼叫深度。

答案 1 :(得分:3)

一般来说,这不是一个非常好的编程方式,因为(除了可能的最大递归深度问题)如果你的程序变得更复杂,你最终会在不同的函数之间跳转多次spaghetti-like ,使其越来越难以阅读和调试。

相反,使用main函数控制整个程序流并调用其他函数更为标准。在两个函数之间更清晰地分离角色也是更好的。

def power_of_two(x):
    y = 1
    while y < x:
        y *= 2
    return y == x

def get_number():
    return int(raw_input('Input a number (type 0 to quit): '))

def main():
    while True:
        n = get_number()
        if n == 0:
            return
        print power_of_two(n)

main()

答案 2 :(得分:2)

不 - 正如已经说过的那样,你有可能遇到堆栈溢出。

你最好做

def power_of_two(x):
    y=1
    z=[]
    while y < x:
        y=y*2
        z.append(y)
    if x in z or x == 1:
        print 'true'
    elif x == 0:
        quit()
    else: 
        print 'false'


def play():
    while True:
        num = int(raw_input('Input a number (type 0 to quit): '))
        power_of_two(num)

这很接近你的解决方案,但远非完美。

最好将功能喷射到它所承诺的范围内:检查数字是否是2的幂,而不是其他任何东西。

def power_of_two(x):
    y = 1
    z = set((1,)) # as only "in" is performed, a set is better here...
    # Having 1 in the set initially saves the extra check for x == 1...
    while y < x:
        y = y * 2
        z.append(y)
    return x in z


def play():
    while True:
        num = int(raw_input('Input a number (type 0 to quit): '))
        if num == 0:
            return # or just break
        else:
            print power_of_two(num) # prints "True" or "False"
            print 'true' if power_of_two(num) else 'false' # prints "true" or "false"

如果你想使用for循环,你可以用生成器的形式创建一个iterable,它产生值直到不再有:

def numbers():
    while True:
        num = int(raw_input('Input a number (type 0 to quit): '))
        if num == 0:
            return # or just break
        else:
            yield num

def play():
    for num in numbers():
        # power_of_two() is the same as above.
        print power_of_two(num) # prints "True" or "False"
        print 'true' if power_of_two(num) else 'false' # prints "true" or "false"

即使这个内部while循环也可以用for循环替换,例如: G。计数:

def numbers():
    import itertools
    for round in itertools.count(1):
        num = int(raw_input('Input number ' + str(round) + ' (type 0 to quit): '))
        if num == 0:
            return # or just break
        else:
            yield num
相关问题