将变量从子例程全球化到另一个子例程

Globalising variables from sub-routine into another sub-routine

我在将我的变量从一个子例程转移到另一个子例程时遇到了一些麻烦。

代码如下:

def loop1():
    try:
        age=int(input("How old are you? "))
    except ValueError:
        print ("Please enter a numerical integer of your age. For example: 19 ")
        print("")
        loop1()
    if age>0:
        program()

def program():
    print("")
    print("[1] - Knife / Spray Paint / Lottery Ticket ")
    print("[2] - Alcohol / Tobacco ")
    print("[3] - Anything else ")
    print("")
    loop2()

def loop2():
    try:
        item=int(input("What would you like to buy from the options above? "))
        print("")
    except ValueError:
        print ("Please enter a numerical integer of your item. For example (if you wanted to buy alcohol): 2 ")
        print("")
        loop2()
    if item>0:
        validation()

def validation(): 
    if item == 1 and 16>age :
        print("Sale Denied - Item cannot be sold to Under 16s. ")
    elif item == 1 and 16<age:
        print("Sale Accepted. ")

    elif item == 2 and 18>age:
        print("Sale Denied - Item cannot be sold to Under 18s. ")
    elif item == 2 and 25>age>18:
        print("Check ID before selling alcohol - Challenge 25. ")
    elif item == 2 and 18<age:
        print("Sale Accepted. ")

    elif item == 3:
        print("Sale Accepted. ")

loop1()

结果如下:

How old are you? 21

[1] - Knife / Spray Paint / Lottery Ticket 
[2] - Alcohol / Tobacco 
[3] - Anything else 

What would you like to buy from the options above? 2

Traceback (most recent call last):
  File "D:/Shop Program.py", line 48, in <module>
    loop1()
  File "D:/Test.py", line 9, in loop1
    program()
  File "D:/Shop Program.py", line 17, in program
    loop2()
  File "D:/Shop Program.py", line 28, in loop2
    validation()
  File "D:/Shop Program.py", line 33, in validation
    if item == 1 and 16>age :
NameError: global name 'item' is not defined

正如您从上面的错误消息中看到的那样,它表示 global name 'item' is not defined。我尝试将 global item 放在 def vaildation(): 上方,但我仍然遇到同样的错误。

而不是使用 global,这是一个 bad practice(在 Python 和其他任何地方),明确地将 itemloop2 传递到 validation:

def loop2(age):
    ...
    if item > 0:
        validation(item, age)
                 # ^ pass it here

def validation(item, age): 
             # ^ receive it here
    if item == 1 and 16 > age:
        ...

注意我对age也做了类似的事情,应该在调用loop2的时候传入。使用递归进行输入验证并不理想;请参阅 Asking the user for input until they give a valid response 了解另一种方法。

如果您已经知道这一点,请原谅我,但是还有另一种方法可以将项目放入 validate 子例程中,这可能更适合您。您可以 "pass in" 一个变量到子例程(也称为方法或函数)。您 "pass in" 给子程序的变量称为参数。 要使用子例程参数,您必须做两件事:

  1. 定义子程序定义中的参数
  2. 调用子程序时指定变量为"pass in"

所以对你来说,在你的 validate 例程中定义参数 item 应该是这样的:

def validate(item):
    if item == 1 and 16>age :

看看我是如何将 item 卡在括号之间的。

然后,您所要做的就是"pass in"验证函数的项目:

def loop2():
try:
    item=int(input("What would you like to buy from the options above? "))
    print("")
except ValueError:
    print ("Please enter a numerical integer of your item. For example (if you wanted to buy alcohol): 2 ")
    print("")
    loop2()
if item>0:
    validation(item)

请注意我是如何在调用最后一行 validation 子例程的括号之间放置 item 的。

希望对您有所帮助

除了您最初的问题:如果出现异常,则在 loop1 和 loop2 中有可能无限递归,因为函数会调用它们自己。

更好的方法是在成功转换后使用带有中断的循环(while True: ...)。

此外,按照您的方式链接函数在每种编程语言中都是不好的做法。这是一个比使用 goto 更糟糕的想法,通常被称为意大利面条代码。 更好的是有一个主函数,它连续调用函数并将前一个函数的结果作为参数传递给下一个函数:

age = get_age()
item = get_item()
if age < 16 and item == ...:
    print("Not allowed")
...

更好的方法是使用 { "item" : minimal_age }:

的字典
items = { "butter": 0 , "knife": 16, "booze": 18, "beer": 17 }

age = ...
item = get_item(items)    # the list can be built automatically from dict
if age < items[item]:
    print("Too young for", item)
else:
    purchase(item)

这将避免 if .. elif .. 测试的冗长列表。 如果项目由字符串而不是数字标识,那将增加可读性。一般来说,在 Python 中,numberincal 值应该只在它们是 "natural" 的地方使用,否则使用适当的类型,如字符串、集合等。 请注意,这与其他语言(例如 C)不同,在其他语言中,字符串处理非常不方便且代价高昂。