不带参数输入的可变功能范围

时间:2017-10-04 08:18:26

标签: python python-3.x function scope

我试图理解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()是明确的。然后我运行function_a(),其中A被赋值为1.

因此,在function_a()的范围内,变量A = 1存在。

然后调用function_b()并打算打印变量A的值。在function_b()的范围内不存在A.因此,我希望它看起来更高,这是function_a()的范围,因为function_b()function_a()内运行。

但显然,我错了。实际发生了什么?

4 个答案:

答案 0 :(得分:6)

仅仅因为你在function_b内调用function_a并不意味着它会继承function_a的范围并且有充分的理由。该函数从其定义的范围获取范围,而不是它被调用的位置。

如果你想完成像closures这样的事情,你应该尝试在function_b内定义function_a

def function_a(A):
     def function_b():
         print(A)

话虽如此,我还没有真正看到一个关闭用例。你最好将变量作为参数传递。这样,它将更具可重用性和可测试性。

def function_a(A):
    function_b(A)

def function_b(A):
    print(A)

答案 1 :(得分:3)

  

因此我希望它看起来更高,这将是   范围function_a()因为function_b()在其中运行   function_a()

确实看起来更高。但function_a的范围并不高于function_b的范围。范围有些独立。不要将作用域层次结构与堆栈帧混淆。层次结构中的下一个范围是模块范围,这里是全局范围; A不在全球范围内。

要访问A中的function_b,您可以将其作为参数传递给function_b或在模块范围内定义A

答案 2 :(得分:1)

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打印的结果,因为查找会成功。

答案 3 :(得分:0)

我认为这是因为python没有将绑定放在变量绑定接收的同一命名空间中的参数。参数绑定仅存在于函数的范围内。

实现效果的正确方法是使用python闭包(它包含其父函数的命名空间):

def function_a(A):
    def function_b():
        print(A)

    function_b()

function_a(1)

您可以简单地将值A传递给两个函数,但这可能表明您应该创建一个包含A的类(特别是如果许多函数需要A):< / p>

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()