命名空间问题:可变变量不需要在函数中声明为全局变量?

时间:2016-09-11 17:13:20

标签: python

我是python的新手,我试图弄清楚如何通过函数传递值。我观察到以下行为

EX1:

def func1():
    a = 1
    b.add('b')

a = 0
b = set()
func1()
print(a,b) 

结果是0 {'b'}

a和b都没有被声明为全局,但是对b的赋值改变了b的全局值,是因为b是可变变量吗?

EX2:

def func1():
    b.add('b')

def func2():
    b = set()
    func1()

func2()
print(b)

Traceback (most recent call last):
  File "test_variables.py", line 10, in <module>
    func2()
  File "test_variables.py", line 8, in func2
    func1()
  File "test_variables.py", line 4, in func1
    b.add('b')
NameError: name 'b' is not defined

为什么在这种情况下,b不能在func1()中分配?

EX3:

我必须将变量从函数传递给函数

def func1(b):
    b.add('b')

def func2():
    b = set()
    func1(b)
    print(b)

func2()

这次打印{'b'}

EX4:

我还可以做的是在外面定义b

def func1():
    b.add('b')

def func2():    
    func1()
    print(b)

b = set()
func2()

它也打印{'b'}

提前感谢您的帮助

4 个答案:

答案 0 :(得分:0)

当你将一个可变变量传递给你通过引用传递的函数时,这意味着你要创建另一个变量(它只存在于函数的范围内),它指向同一个对象。

此外,Python以您可以使用的方式工作,并查看您在外部范围内的变量(这就是ex1中您可以添加内容的原因

EX1 中,func1()知道ab,但无法为其分配值(除非您在函数内部将它们定义为global !)。当您执行a = 1时,python只会创建一个新的a变量,该变量仅存在于该函数内。
b.add('b')是可能的,因为你指的是set对象(这是不可变的)。如果您尝试在函数内部使用b = 'b'之类的内容,请再次创建一个本地b变量,并保持外部集不受影响。

答案 1 :(得分:0)

以下是基于Python Language Reference "Naming and Binding"文档中给出的解释的简化答案。

让我们看看你的第一个例子:

def func1():
    a = 1
    b.add('b')

在此示例中,您执行两项单独的操作。

首先,您将值1绑定取值为a。此绑定在包含其执行的范围内发生 :在这种情况下,范围是函数func1

其次,您查找与名称b相关联的值,并在该值上调用方法add。由于这是一个查找,而不是绑定,它不仅限于立即封闭范围,而是会找到包含该名称的最近的封闭范围。在这种情况下,由于函数func1的范围不包含名称b,因此将检查下一个封闭范围:这是全局范围, 包含名称b,这就是使用的值。

答案 2 :(得分:0)

你的问题叫做范围。范围是在哪里定义的通用名称。所以当你声明一个变量时:

b = 0

任何处于相同范围或更低范围的东西都可以看到它的定义。

b = 1
def func():
    print(b)

func()

这是有效的,因为b已经在该范围内定义,在这种情况下,b是全局的(一切都可以看到它的定义)。

def func():
    b = 0

def func1():
    print(b)

func()
func1()

这不起作用,因为b现在是一个局部变量,它只在func()中定义,而不是func1()

b = 1
def func():
    b = 0

def func1():
    print(b)

func()
func1()

这将打印0,因为b是在全局级别定义的。将全局变量设置为新值,无论您在何处执行此操作,都将始终使该新值全局可用

但你也必须考虑订购。

print(b)
b = 1

不起作用

b = 1
print(b)
b = 0

将打印b = 1,因为在打印之前该值未设置为0

答案 3 :(得分:0)

此博文(1)解释了Python的参数传递。

在示例1中声明b时,您将其全局声明。

在示例2中,您覆盖名称b,因此仅在func2中知道,这就是为什么func1不知道任何b。

希望这会有所帮助:)