变量不可用于子功能[重复]

问题描述 投票:0回答:4

此脚本在

main()
内部定义了一个变量,但该变量不可用于在
func()
内部运行的
main()
。这是为什么?

#!/usr/bin/env python3
# vars_in_func.py
# Test script for variables within a function.

def func():
  print(greeting)

def main():
  greeting = "Hello world"
  func()

main()

错误:

Traceback (most recent call last):
  File "./vars_in_func.py", line 11, in <module>
    main()
  File "./vars_in_func.py", line 9, in main
    func()
  File "./vars_in_func.py", line 5, in func
    print(greeting)
NameError: name 'greeting' is not defined

如果我将脚本转换为 Python2,错误是相同的,只不过它显示的是

global name
而不是
name

我想我只是错过了一个关键概念。我在学习 Bash 后才开始学习 Python。

编辑:阅读完答案后,我意识到我的错误:我仍在思考 Bash,其中函数要么在与调用者相同的 shell 中运行(具有相同的变量),要么在调用者的子 shell 中运行(继承变量)。

python function variables
4个回答
5
投票
greeting = None

def func():
    print(greeting)

def main():
   global greeting
   greeting = "Hello world"
   func()

main()

在您的解决方案中,主函数中定义的greeting是局部变量,无法在主函数之外访问。这就是它给你错误的原因


2
投票

我对Python了解不多,但一般来说,全局变量需要在main范围之外定义,但要在要使用它们的函数之前定义。如果你不想使变量成为全局变量,则需要传递变量作为参数传入函数。


1
投票

关于 python 作用域规则有很多答案,这在这里确实很重要。但正如我看到你的问题,你的误解在于完全不同的东西:定义函数和调用它之间存在巨大差异。

LEGB 规则很重要,但真正重要的是 “虽然范围是静态确定的,但它们是动态使用的”。粗略地说,函数知道在哪里寻找变量(编译时),但它不知道变量值(在调用函数之前)。

在您的情况下,您只需将一个函数调用到另一个函数的主体中即可。当您调用函数时,调用者将控制权传递给被调用者(粗略地,将其想象为源代码中跳转到函数代码块的开头)。因此,当您呼叫

func
时,您就会跳入
func
身体。此函数尝试查找名称:
print
greeting
(此过程称为 名称解析)。它在
local
范围中查找,然后在
global
范围(定义它的范围,不称为)中查找,最后在
builtins
中查找。它在
print
中仅找到
builtins
。因为它没有找到
greeting
名称,所以会引发异常
NameError
。在检测到错误的地方引发异常,在您的情况下,在
main
称为
func
的地方引发异常。当根本没有处理异常时,解释器将终止程序的执行,或返回到其交互式主循环。无论哪种情况,它都会打印堆栈跟踪,除非异常为
SystemExit

还有一个查找信息的地方:Python 语言参考:执行模型

p.s.:全局范围始终是定义函数的模块(带有代码的文件)。理解这一点非常重要!!!


0
投票

在Python中,函数不能访问函数外部的任何变量,除非它是一个参数或被声明

global

这有望解决问题:

greeting = None

def func():
    print(greeting)

def main():
   global greeting # Declaring as global means func() can access it
   greeting = "Hello world"
   func()

main()
© www.soinside.com 2019 - 2024. All rights reserved.