关于python:嵌套函数是Pythonic吗?

Is Nesting Functions Pythonic?

我正在用R.PI学习Python,我遇到了一个小问题。在我看来,下面的代码会让"inputchecker"函数在内存中保持打开状态,同时它会返回到"getinput"函数。

这是坏代码吗?是否应该做得非常不同?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def getinput(i):    
    if i == 1:
        first = input("Would you like A or B?")
        inputchecker(1, first)
    elif i == 2:
        second = input("Would you like C or D?")
        inputchecker(2, second)

def inputchecker(n, userinput):    
    def _tryagain_(n):
        usage(n)
        getinput(n)        
    if n == 1:
        if userinput in ("A","B"):
            print("You chose wisely.")
            getinput(2)
        else:
            _tryagain_(n)
    elif n == 2:
        if userinput in ("C","D"):
            print("You chose wisely.")
        else:
            _tryagain_(n)

def usage(u):
    if u == 1:
        print("Usage: Just A or B please.")
    if u == 2:
        print("Usage: Just C or D please.")


getinput(1)


不,嵌套函数中的名称getinput不会创建引用。每次调用_tryagain_时都会查找它,因为它是全局的。这并不重要,因为当Python退出时,模块作为一个整体被清除,所以这里没有发生内存泄漏的真正机会。

但是,您使用递归请求用户输入,您的代码很难执行。使用一个简单的循环,请参见询问用户输入,直到他们给出有效的响应。


拥有两个彼此无限调用的函数并不是最好的控制流。用一个while循环会更好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def getinput(i):
    while i:    
        if i == 1:
            first = input("Would you like A or B?")
            i = inputchecker(1, first)
        elif i == 2:
            second = input("Would you like C or D?")
            i = inputchecker(2, second)

def inputchecker(n, userinput):          
    if n == 1:
        if userinput in ("A","B"):
            print("You chose wisely.")
            return 2
        else:
            getusage(i)
            return i
    elif n == 2:
        if userinput in ("C","D"):
            print("You chose wisely.")
        else:
            getusage(i)
            return i

如果将其简化为单个函数,可能会更好。没有理由要分开。


我当然会避免递归调用。另外,我会让验证函数返回一个布尔值,而不是下一个问题的编号。由于您总是按顺序问问题,这似乎只会使代码的读者感到复杂。

另外,我会让验证总是返回一些东西——你永远不会知道:第一个参数也可能是错误的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def getinput():
    valid = False
    while not valid:
        first = input("Would you like A or B?")
        valid = inputIsValid(1, first)
    valid = False
    while not valid:
        second = input("Would you like C or D?")
        valid = inputIsValid(2, second)
    return [first, second]

def inputIsValid(n, userinput):    
    valid = False
    if n == 1:
        valid = userinput in ("A","B")
    elif n == 2:
        valid = userinput in ("C","D")
    if valid:
        print("You chose wisely.")
    else:
        usage(n)
    return valid

def usage(u):
    if u == 1:
        print("Usage: Just A or B please.")
    elif u == 2:
        print("Usage: Just C or D please.")

getinput()