I'm writing a program and I'm using espeak
library to make it speak. The thing is I've already written my program but now I want to make a way to ask the user in the beginning if he wants the program to talk to him or just rely on reading. So if he said yes the program speaks using espeak
, but if he said no the program does not use espeak
, so I'm stuck at the no part.
I want to ask a question and use the right function based on the answer, but the problem is that its a local function so when you use the function espeak()
it says
NameError: name 'espeak' is not defined
Here's how what I want it:
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?")
So is there a way to make that def espeak()
function work on a global level so I can use it for the rest of my program?
(other than coping the hole thing and pasting it in the no section without the espeak
function)
Here's how to write it such that speak_or_not
returns the espeak
function. I've added type annotations to make it easier to see how the inner function interacts with the outer function -- the speak_or_not
function returns a Callable[[str], None]
(a function that takes a str
argument and returns None
), and both version of espeak
match this type.
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?")
Note that the global ai_talk
is not necessary because this value was never used outside of the function, and in fact within the function it's only ever used to break the loop, which is unnecessary if you return
once the terminating condition is met, so even within the function the value is not needed at all.