你能以某种方式在 python 中使用全局级别的局部函数吗?

Can you somehow use a local function on a global level in python?

我正在编写一个程序,我正在使用 espeak 库让它说话。问题是我已经编写了我的程序,但现在我想在一开始就询问用户他是否希望程序与他交谈或只是依靠阅读。因此,如果他说是,程序将使用 espeak 说话,但如果他说否,程序将不使用 espeak,所以我被困在了 no 部分。

我想问一个问题并根据答案使用正确的函数,但问题是它是一个局部函数,所以当你使用函数 espeak() 时它说

NameError: name 'espeak' is not defined 

这是我想要的:

import os
ai_talk = False
# MAKE THE AI SPEAK, OR NOT
def speak_or_not():
    global ai_talk
    
    speak_or_n = input("Do you want me to speak or not?\nPS: input Y/N\n").casefold()
    while not ai_talk:
        if (speak_or_n == "y") or (speak_or_n == "yes"):
            def espeak(text):
                command = 'espeak -v +f2 -p25 '+'"'+text+'"'
                os.system(command)
                return
            ai_talk = True

        elif (speak_or_n == "n") or (speak_or_n == "no"):
            def espeak(text):
                return
            ai_talk = True

        else:
            speak_or_n = input("You can only input Y/N").casefold()
    return

speak_or_not()

print("Hello there! how are you doing?")
espeak("Hello there! how are you doing?")

那么有没有办法让 def espeak() 函数在全球范围内工作,以便我可以在我的程序的其余部分使用它?

(除了在没有 espeak 功能的情况下处理漏洞并将其粘贴到 no 部分)

如果你只是return espeak,你可以在主程序中保存你想要的定义。 Python 装饰器就是这样工作的。这是一个简单的例子:

def fpick(flag):
    if flag:
        def display():
            print('flag was set')
    else:
        def display():
            print('flag was off')

    return display

display = fpick(True)
display()

display = fpick(False)
display()

输出:

flag was set
flag was off

 was set
flag

已关闭

下面是如何编写它使得 speak_or_not returns espeak 函数。我添加了类型注释,以便更容易地查看内部函数如何与外部函数交互——speak_or_not 函数 returns a Callable[[str], None](一个函数接受 str 参数和 returns None),并且 espeak 的两个版本都匹配此类型。

import os
from typing import Callable

def speak_or_not() -> Callable[[str], None]:
    """Return a function that either makes the AI speak or is a no-op."""
    speak_or_n = input("Do you want me to speak or not?\nPS: input Y/N\n").casefold()
    while True:
        if speak_or_n in ("y", "yes"):
            def espeak(text: str) -> None:
                os.system(f'espeak -v +f2 -p25 "{text}"')
            return espeak
        if speak_or_n in ("n", "no"):
            def espeak(text: str) -> None:
                return
            return espeak
        speak_or_n = input("You can only input Y/N").casefold()

espeak = speak_or_not()

print("Hello there! how are you doing?")
espeak("Hello there! how are you doing?")

请注意 global ai_talk 不是必需的,因为该值从未在函数外部使用过,实际上在函数内部它仅用于中断循环,如果您 return 一旦满足终止条件,因此即使在函数内也根本不需要该值。