不带参数输入的函数变量范围
我想了解Python(3.x)中的变量作用域,但下面是一个不起作用的代码示例,我不知道为什么。不带参数输入的函数变量范围
def function_a(A):
function_b()
def function_b():
print(A)
function_a(1)
导致NameError: name 'A' is not defined
所以,我认为它的工作方式是,function_a()
和function_b()
是definid。之后,我运行function_a()
,其中A
被赋值为1.
因此在function_a()
的范围内存在变量A = 1。
然后function_b()
被调用并打算打印变量A
的值。 A不存在于function_b()的作用域中。因此,我认为它会看起来更高,这将是function_a()
的范围,因为function_b()
在function_a()
内运行。
但很明显,我错了。究竟发生了什么?
只是因为你有叫function_b
的function_a
内并不意味着我t会继承function_a
的范围,并有充分的理由。该函数从它定义的地方获取范围,而不是它被调用的地方。
如果您想完成类似closures
的操作,您应该尝试在function_a
的内部定义function_b
。
def function_a(A):
def function_b():
print(A)
就这样说,我并没有真正看到这里的封闭用例。您最好将变量作为参数传递。这样它会更加可重用和可测试。
def function_a(A):
function_b(A)
def function_b(A):
print(A)
因此,我希望它看起来级别更高,因为
function_b()
是内function_a()
它看起来更高版本上运行这将是function_a()
的 范围。但function_a
的范围不高于function_b
的范围。范围有些独立。不要将范围层次与堆栈框架混淆。层次结构中的下一个范围是模块范围,这里是全局范围; A
不在全球范围内。
要访问function_b
中的A
,您可以将其作为参数传递给function_b
或在模块范围中定义A
。
Upvoted,但我认为你应该考虑用一种对新手更容易理解的方式来描述它 - IMO在这里有太多技术术语(“范围层级”,“堆栈框架”),当你可以表达相同的通过说“像函数的作用域取决于它的位置_defined_,而不是它被调用的位置”这样一种更清晰的方式。 –
@Rawing感谢您的反馈。我想这就是接受的答案,而且很可能是为什么它被接受。学习...... –
作为提问者,我可以证实这确实是我接受@ hspandher的答案的原因。我也提出了你的回答,因为它确实回答了这个问题。我只是认为另一个答案说得更清楚一些,说'函数从定义的范围获取范围,而不是它被调用的地方'。 感谢您的回答,虽然 – elevendollar
会发生什么事是,在function_b
,在全球范围内的搜索完,因为全球范围内没有定义名称A
和没有封闭的功能范围存在,你会得到一个NameError
。
如果一个封闭的范围存在:
def function_a(A):
def function_b():
print(A)
function_b()
function_a(1) # prints 1
或全局名称A
定义:
A = 2
def function_a(A):
function_b()
def function_b():
print(A)
function_a(1) # prints 2 (finds global name A)
你会得到的A
因为查找将成功打印的结果。
我假设发生这种情况是因为python没有将绑定参数放置在变量绑定接收的同一个命名空间中。参数绑定仅存在于函数的范围内。
正确的方法实现的是使用python关闭您的影响(其包围他们的父母函数的命名空间):
def function_a(A):
def function_b():
print(A)
function_b()
function_a(1)
您可能值A
简单地传递给这两种功能,但这可能会建议你做含A
类(特别是如果A
是由许多功能要求):
class A(object):
def __init___(self, a):
self.a = a
def function_a(self):
self.function_b()
def function_b(self):
print(self.a)
foo = A(1)
foo.function_a()
虽然它不是_directly_有关这个问题,我怀疑你会发现这篇文章有帮助:关于Python的名称和值事实与神话(http://nedbatchelder.com/text/names.html) ,这是由SO老将Ned Batchelder写的。 –