标签归档:dynamic-languages

范围规则的简短描述?

问题:范围规则的简短描述?

Python范围规则到底是什么?

如果我有一些代码:

code1
class Foo:
   code2
   def spam.....
      code3
      for code4..:
       code5
       x()

在哪里x找到?一些可能的选择包括以下列表:

  1. 在随附的源文件中
  2. 在类命名空间中
  3. 在函数定义中
  4. 在for循环中,索引变量
  5. 在for循环内

当函数spam传递到其他地方时,执行期间还会有上下文。也许lambda函数传递的方式有所不同?

某个地方必须有一个简单的参考或算法。对于中级Python程序员而言,这是一个令人困惑的世界。

What exactly are the Python scoping rules?

If I have some code:

code1
class Foo:
   code2
   def spam.....
      code3
      for code4..:
       code5
       x()

Where is x found? Some possible choices include the list below:

  1. In the enclosing source file
  2. In the class namespace
  3. In the function definition
  4. In the for loop index variable
  5. Inside the for loop

Also there is the context during execution, when the function spam is passed somewhere else. And maybe lambda functions pass a bit differently?

There must be a simple reference or algorithm somewhere. It’s a confusing world for intermediate Python programmers.


回答 0

实际上,这是学习Python的第3条关于Python范围解析的简明规则埃德 。(这些规则特定于变量名,而不是属性。如果不加句点引用,则适用这些规则。)

LEGB规则

  • L ocal —在函数(deflambda)中以任何方式分配的名称,但未在该函数中声明为全局

  • E nclosing-function —在任何和所有静态封装函数(deflambda)的本地范围内从内部到外部分配的名称

  • ģ叶形(模块) -在模块文件的顶层分配名称,或通过执行global在声明def文件中

  • : – uilt式(Python)的名称在内置模块的名称预先分配的openrangeSyntaxError,等

因此,在

code1
class Foo:
    code2
    def spam():
        code3
        for code4:
            code5
            x()

for循环中没有自己的名字空间。按照LEGB顺序,范围为

  • L:本地的def spam(在code3code4code5
  • E:任何封闭函数(如果整个示例都在另一个示例中def
  • G:x模块中的全局中是否有任何声明code1
  • B:任何内置x的Python。

x永远不会被发现code2(即使您可能会期望,也请参阅Antti的答案此处)。

Actually, a concise rule for Python Scope resolution, from Learning Python, 3rd. Ed.. (These rules are specific to variable names, not attributes. If you reference it without a period, these rules apply.)

LEGB Rule

  • Local — Names assigned in any way within a function (def or lambda), and not declared global in that function

  • Enclosing-function — Names assigned in the local scope of any and all statically enclosing functions (def or lambda), from inner to outer

  • Global (module) — Names assigned at the top-level of a module file, or by executing a global statement in a def within the file

  • Built-in (Python) — Names preassigned in the built-in names module: open, range, SyntaxError, etc

So, in the case of

code1
class Foo:
    code2
    def spam():
        code3
        for code4:
            code5
            x()

The for loop does not have its own namespace. In LEGB order, the scopes would be

  • L: Local in def spam (in code3, code4, and code5)
  • E: Any enclosing functions (if the whole example were in another def)
  • G: Were there any x declared globally in the module (in code1)?
  • B: Any builtin x in Python.

x will never be found in code2 (even in cases where you might expect it would, see Antti’s answer or here).


回答 1

本质上,Python中唯一引入新作用域的就是函数定义。类是一种特殊情况,因为直接在主体中定义的所有内容都放置在类的命名空间中,但是不能从它们包含的方法(或嵌套类)中直接访问它们。

在您的示例中,只有3个范围可以在其中搜索x:

  • 垃圾邮件的范围-包含在code3和code5(以及code4,循环变量)中定义的所有内容

  • 全局范围-包含code1中定义的所有内容以及Foo(及其后的所有更改)

  • 内置命名空间。有点特殊的情况-它包含各种Python内置函数和类型,例如len()和str()。通常,不应由任何用户代码对此进行修改,因此希望它包含标准功能,而不包含其他任何功能。

仅当您在图片中引入嵌套函数(或lambda)时,才会出现更多作用域。但是,它们的行为几乎与您期望的一样。嵌套函数可以访问本地作用域中的所有内容以及封闭函数的作用域中的任何内容。例如。

def foo():
    x=4
    def bar():
        print x  # Accesses x from foo's scope
    bar()  # Prints 4
    x=5
    bar()  # Prints 5

限制条件:

可以访问除局部函数的变量之外的范围中的变量,但是如果没有进一步的语法,则不能将其反弹到新参数。相反,赋值将创建一个新的局部变量,而不是影响父作用域中的变量。例如:

global_var1 = []
global_var2 = 1

def func():
    # This is OK: It's just accessing, not rebinding
    global_var1.append(4) 

    # This won't affect global_var2. Instead it creates a new variable
    global_var2 = 2 

    local1 = 4
    def embedded_func():
        # Again, this doen't affect func's local1 variable.  It creates a 
        # new local variable also called local1 instead.
        local1 = 5
        print local1

    embedded_func() # Prints 5
    print local1    # Prints 4

为了在功能范围内实际修改全局变量的绑定,需要使用global关键字指定变量是全局变量。例如:

global_var = 4
def change_global():
    global global_var
    global_var = global_var + 1

当前,对于封闭函数范围中的变量,没有任何方法可以做到,但是Python 3引入了一个新关键字“ nonlocal”,它的作用与全局变量类似,但对于嵌套函数范围而言。

Essentially, the only thing in Python that introduces a new scope is a function definition. Classes are a bit of a special case in that anything defined directly in the body is placed in the class’s namespace, but they are not directly accessible from within the methods (or nested classes) they contain.

In your example there are only 3 scopes where x will be searched in:

  • spam’s scope – containing everything defined in code3 and code5 (as well as code4, your loop variable)

  • The global scope – containing everything defined in code1, as well as Foo (and whatever changes after it)

  • The builtins namespace. A bit of a special case – this contains the various Python builtin functions and types such as len() and str(). Generally this shouldn’t be modified by any user code, so expect it to contain the standard functions and nothing else.

More scopes only appear when you introduce a nested function (or lambda) into the picture. These will behave pretty much as you’d expect however. The nested function can access everything in the local scope, as well as anything in the enclosing function’s scope. eg.

def foo():
    x=4
    def bar():
        print x  # Accesses x from foo's scope
    bar()  # Prints 4
    x=5
    bar()  # Prints 5

Restrictions:

Variables in scopes other than the local function’s variables can be accessed, but can’t be rebound to new parameters without further syntax. Instead, assignment will create a new local variable instead of affecting the variable in the parent scope. For example:

global_var1 = []
global_var2 = 1

def func():
    # This is OK: It's just accessing, not rebinding
    global_var1.append(4) 

    # This won't affect global_var2. Instead it creates a new variable
    global_var2 = 2 

    local1 = 4
    def embedded_func():
        # Again, this doen't affect func's local1 variable.  It creates a 
        # new local variable also called local1 instead.
        local1 = 5
        print local1

    embedded_func() # Prints 5
    print local1    # Prints 4

In order to actually modify the bindings of global variables from within a function scope, you need to specify that the variable is global with the global keyword. Eg:

global_var = 4
def change_global():
    global global_var
    global_var = global_var + 1

Currently there is no way to do the same for variables in enclosing function scopes, but Python 3 introduces a new keyword, “nonlocal” which will act in a similar way to global, but for nested function scopes.


回答 2

关于Python3时间,还没有详尽的答案,所以我在这里做了一个答案。4.2.2 Python 3文档名称解析详细介绍了此处描述的大部分内容。

如其他答案中所提供的,本地,封闭,全局和内置有4个基本范围,即LEGB。除此以外,还有一个特殊的范围,即类主体,它不包含该类中定义的方法的封闭范围;类主体内的任何赋值都会使变量从此绑定到类主体中。

特别是,除了和之外,没有块语句创建变量作用域。在Python 2中,列表推导不会创建变量作用域,但是在Python 3中,列表推导内的循环变量是在新作用域中创建的。defclass

证明Class机构的特殊性

x = 0
class X(object):
    y = x
    x = x + 1 # x is now a variable
    z = x

    def method(self):
        print(self.x) # -> 1
        print(x)      # -> 0, the global x
        print(y)      # -> NameError: global name 'y' is not defined

inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)

因此,与函数主体不同,您可以在类主体中将变量重新分配给相同的名称,以获得具有相同名称的类变量。对该名称的进一步查找将解析为class变量。


对于Python的许多新手来说,最大的惊喜之一就是for循环不会创建变量作用域。在Python 2中,列表推导也不创建作用域(而generator和dict则创建!)而是泄漏函数或全局范围中的值:

>>> [ i for i in range(5) ]
>>> i
4

理解可以用作在Python 2中的lambda表达式内创建可修改变量的一种狡猾(或者如果您愿意的话)的方法-lambda表达式确实会创建变量作用域,就像该def语句那样,但是在lambda中不允许使用任何语句。赋值是Python中的语句,表示不允许在lambda中进行变量赋值,但列表推导是一个表达式…

此行为已在Python 3中修复-没有理解表达式或生成器会泄漏变量。


全局实际上意味着模块范围;主要的python模块是__main__; 所有导入的模块都可以通过该sys.modules变量访问;获得__main__可以使用的权限sys.modules['__main__'],或import __main__; 在那里访问和分配属性是完全可以接受的;它们将作为变量显示在主模块的全局范围内。


如果在当前作用域中分配了名称(在类作用域中除外),则该名称将被视为属于该作用域,否则将被视为属于任何分配给该变量的封闭作用域(可能未分配)然而,或者根本没有),或者最后是全球范围。如果该变量被认为是局部变量,但尚未设置或已被删除,则读取变量值将导致UnboundLocalError,这是的子类NameError

x = 5
def foobar():
    print(x)  # causes UnboundLocalError!
    x += 1    # because assignment here makes x a local variable within the function

# call the function
foobar()

作用域可以声明它要使用global关键字明确修改全局变量(模块作用域):

x = 5
def foobar():
    global x
    print(x)
    x += 1

foobar() # -> 5
print(x) # -> 6

即使它被封闭在范围内,这也是可能的:

x = 5
y = 13
def make_closure():
    x = 42
    y = 911
    def func():
        global x # sees the global value
        print(x, y)
        x += 1

    return func

func = make_closure()
func()      # -> 5 911
print(x, y) # -> 6 13

在python 2中,没有简单的方法可以在封闭范围内修改值;通常,这是通过具有可变值(例如长度为1的列表)来模拟的

def make_closure():
    value = [0]
    def get_next_value():
        value[0] += 1
        return value[0]

    return get_next_value

get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2

但是,在python 3中,nonlocal可以进行救援:

def make_closure():
    value = 0
    def get_next_value():
        nonlocal value
        value += 1
        return value
    return get_next_value

get_next = make_closure() # identical behavior to the previous example.

nonlocal文件

与在全局语句中列出的名称不同,非本地语句中列出的名称必须引用封闭范围内的现有绑定(不能明确确定应在其中创建新绑定的范围)。

即,nonlocal始终是指已绑定名称的最内层外部非全局范围(即,分配给该全局for变量,包括在with子句中或用作函数参数,包括用作目标变量)。


任何不被认为是当前作用域或任何封闭作用域局部变量的变量都是全局变量。在模块全局词典中查找全局名称;如果找不到,则从内建模块中查找全局变量;模块的名称从python 2更改为python 3; 在python 2中曾经是__builtin__,在python 3中现在被称为builtins。如果分配给buildins模块的属性,此后它将以可读的全局变量的形式对任何模块可见,除非该模块用自己的同名全局变量来遮盖它们。


读取内置模块也很有用;假设您希望在文件的某些部分使用python 3样式的打印功能,但文件的其他部分仍使用该print语句。在Python 2.6-2.7中,您可以使用以下命令来掌握Python 3 print函数:

import __builtin__

print3 = __builtin__.__dict__['print']

from __future__ import print_function实际上不会导入print功能,随时随地在Python 2 -而不是它只是禁止解析规则,print在当前模块中的语句,处理print像任何其他变量标识符,从而使print功能的内建进行查找。

There was no thorough answer concerning Python3 time, so I made an answer here. Most of what is described here is detailed in the 4.2.2 Resolution of names of the Python 3 documentation.

As provided in other answers, there are 4 basic scopes, the LEGB, for Local, Enclosing, Global and Builtin. In addition to those, there is a special scope, the class body, which does not comprise an enclosing scope for methods defined within the class; any assignments within the class body make the variable from there on be bound in the class body.

Especially, no block statement, besides def and class, create a variable scope. In Python 2 a list comprehension does not create a variable scope, however in Python 3 the loop variable within list comprehensions is created in a new scope.

To demonstrate the peculiarities of the class body

x = 0
class X(object):
    y = x
    x = x + 1 # x is now a variable
    z = x

    def method(self):
        print(self.x) # -> 1
        print(x)      # -> 0, the global x
        print(y)      # -> NameError: global name 'y' is not defined

inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)

Thus unlike in function body, you can reassign the variable to the same name in class body, to get a class variable with the same name; further lookups on this name resolve to the class variable instead.


One of the greater surprises to many newcomers to Python is that a for loop does not create a variable scope. In Python 2 the list comprehensions do not create a scope either (while generators and dict comprehensions do!) Instead they leak the value in the function or the global scope:

>>> [ i for i in range(5) ]
>>> i
4

The comprehensions can be used as a cunning (or awful if you will) way to make modifiable variables within lambda expressions in Python 2 – a lambda expression does create a variable scope, like the def statement would, but within lambda no statements are allowed. Assignment being a statement in Python means that no variable assignments in lambda are allowed, but a list comprehension is an expression…

This behaviour has been fixed in Python 3 – no comprehension expressions or generators leak variables.


The global really means the module scope; the main python module is the __main__; all imported modules are accessible through the sys.modules variable; to get access to __main__ one can use sys.modules['__main__'], or import __main__; it is perfectly acceptable to access and assign attributes there; they will show up as variables in the global scope of the main module.


If a name is ever assigned to in the current scope (except in the class scope), it will be considered belonging to that scope, otherwise it will be considered to belonging to any enclosing scope that assigns to the variable (it might not be assigned yet, or not at all), or finally the global scope. If the variable is considered local, but it is not set yet, or has been deleted, reading the variable value will result in UnboundLocalError, which is a subclass of NameError.

x = 5
def foobar():
    print(x)  # causes UnboundLocalError!
    x += 1    # because assignment here makes x a local variable within the function

# call the function
foobar()

The scope can declare that it explicitly wants to modify the global (module scope) variable, with the global keyword:

x = 5
def foobar():
    global x
    print(x)
    x += 1

foobar() # -> 5
print(x) # -> 6

This also is possible even if it was shadowed in enclosing scope:

x = 5
y = 13
def make_closure():
    x = 42
    y = 911
    def func():
        global x # sees the global value
        print(x, y)
        x += 1

    return func

func = make_closure()
func()      # -> 5 911
print(x, y) # -> 6 13

In python 2 there is no easy way to modify the value in the enclosing scope; usually this is simulated by having a mutable value, such as a list with length of 1:

def make_closure():
    value = [0]
    def get_next_value():
        value[0] += 1
        return value[0]

    return get_next_value

get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2

However in python 3, the nonlocal comes to rescue:

def make_closure():
    value = 0
    def get_next_value():
        nonlocal value
        value += 1
        return value
    return get_next_value

get_next = make_closure() # identical behavior to the previous example.

The nonlocal documentation says that

Names listed in a nonlocal statement, unlike those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously).

i.e. nonlocal always refers to the innermost outer non-global scope where the name has been bound (i.e. assigned to, including used as the for target variable, in the with clause, or as a function parameter).


Any variable that is not deemed to be local to the current scope, or any enclosing scope, is a global variable. A global name is looked up in the module global dictionary; if not found, the global is then looked up from the builtins module; the name of the module was changed from python 2 to python 3; in python 2 it was __builtin__ and in python 3 it is now called builtins. If you assign to an attribute of builtins module, it will be visible thereafter to any module as a readable global variable, unless that module shadows them with its own global variable with the same name.


Reading the builtin module can also be useful; suppose that you want the python 3 style print function in some parts of file, but other parts of file still use the print statement. In Python 2.6-2.7 you can get hold of the Python 3 print function with:

import __builtin__

print3 = __builtin__.__dict__['print']

The from __future__ import print_function actually does not import the print function anywhere in Python 2 – instead it just disables the parsing rules for print statement in the current module, handling print like any other variable identifier, and thus allowing the print the function be looked up in the builtins.


回答 3

其他答案中已经概述了Python 2.x的范围规则。我唯一要补充的是,在Python 3.0中,还有一个非本地范围的概念(由’nonlocal’关键字指示)。这使您可以直接访问外部作用域,并可以进行一些巧妙的技巧,包括词法关闭(没有涉及可变对象的难看的技巧)。

编辑:这是PEP,对此有更多信息。

The scoping rules for Python 2.x have been outlined already in other answers. The only thing I would add is that in Python 3.0, there is also the concept of a non-local scope (indicated by the ‘nonlocal’ keyword). This allows you to access outer scopes directly, and opens up the ability to do some neat tricks, including lexical closures (without ugly hacks involving mutable objects).

EDIT: Here’s the PEP with more information on this.


回答 4

范围的更完整示例:

from __future__ import print_function  # for python 2 support

x = 100
print("1. Global x:", x)
class Test(object):
    y = x
    print("2. Enclosed y:", y)
    x = x + 1
    print("3. Enclosed x:", x)

    def method(self):
        print("4. Enclosed self.x", self.x)
        print("5. Global x", x)
        try:
            print(y)
        except NameError as e:
            print("6.", e)

    def method_local_ref(self):
        try:
            print(x)
        except UnboundLocalError as e:
            print("7.", e)
        x = 200 # causing 7 because has same name
        print("8. Local x", x)

inst = Test()
inst.method()
inst.method_local_ref()

输出:

1. Global x: 100
2. Enclosed y: 100
3. Enclosed x: 101
4. Enclosed self.x 101
5. Global x 100
6. global name 'y' is not defined
7. local variable 'x' referenced before assignment
8. Local x 200

A slightly more complete example of scope:

from __future__ import print_function  # for python 2 support

x = 100
print("1. Global x:", x)
class Test(object):
    y = x
    print("2. Enclosed y:", y)
    x = x + 1
    print("3. Enclosed x:", x)

    def method(self):
        print("4. Enclosed self.x", self.x)
        print("5. Global x", x)
        try:
            print(y)
        except NameError as e:
            print("6.", e)

    def method_local_ref(self):
        try:
            print(x)
        except UnboundLocalError as e:
            print("7.", e)
        x = 200 # causing 7 because has same name
        print("8. Local x", x)

inst = Test()
inst.method()
inst.method_local_ref()

output:

1. Global x: 100
2. Enclosed y: 100
3. Enclosed x: 101
4. Enclosed self.x 101
5. Global x 100
6. global name 'y' is not defined
7. local variable 'x' referenced before assignment
8. Local x 200

回答 5

Python通常使用三个可用的命名空间来解析变量。

在执行过程中的任何时候,至少有三个嵌套作用域可以直接访问其命名空间:最先搜索的最内部作用域包含本地名称;任何封闭函数的命名空间,它们从最近的封闭范围开始搜索;接下来搜索的中间范围包含当前模块的全局名称;最外面的作用域(最后搜索)是包含内置名称的命名空间。

有两个函数:globalslocals,它们向您显示这些命名空间中的两个。

命名空间是由包,模块,类,对象构造和函数创建的。没有其他类型的命名空间。

在这种情况下,x必须在本地命名空间或全局命名空间中解析对名为的函数的调用。

在这种情况下,局部变量是方法函数的主体Foo.spam

全球是-很好-全球。

规则是搜索由方法函数(和嵌套函数定义)创建的嵌套局部空间,然后全局搜索。而已。

没有其他范围。该for语句(以及其他复合语句,如iftry)不会创建新的嵌套作用域。仅定义(包,模块,函数,类和对象实例。)

在类定义中,名称是类命名空间的一部分。 code2,例如,必须由类名限定。一般而言Foo.code2。但是,self.code2由于Python对象会将包含的类视为备用类,因此也可以使用。

对象(类的实例)具有实例变量。这些名称位于对象的命名空间中。它们必须由对象限定。(variable.instance。)

在类方法中,您具有局部变量和全局变量。您说self.variable选择实例作为命名空间。您会注意到,这self是每个类成员函数的参数,使其成为本地命名空间的一部分。

请参见Python作用域规则Python作用域变量作用域

Python resolves your variables with — generally — three namespaces available.

At any time during execution, there are at least three nested scopes whose namespaces are directly accessible: the innermost scope, which is searched first, contains the local names; the namespaces of any enclosing functions, which are searched starting with the nearest enclosing scope; the middle scope, searched next, contains the current module’s global names; and the outermost scope (searched last) is the namespace containing built-in names.

There are two functions: globals and locals which show you the contents two of these namespaces.

Namespaces are created by packages, modules, classes, object construction and functions. There aren’t any other flavors of namespaces.

In this case, the call to a function named x has to be resolved in the local name space or the global namespace.

Local in this case, is the body of the method function Foo.spam.

Global is — well — global.

The rule is to search the nested local spaces created by method functions (and nested function definitions), then search global. That’s it.

There are no other scopes. The for statement (and other compound statements like if and try) don’t create new nested scopes. Only definitions (packages, modules, functions, classes and object instances.)

Inside a class definition, the names are part of the class namespace. code2, for instance, must be qualified by the class name. Generally Foo.code2. However, self.code2 will also work because Python objects look at the containing class as a fall-back.

An object (an instance of a class) has instance variables. These names are in the object’s namespace. They must be qualified by the object. (variable.instance.)

From within a class method, you have locals and globals. You say self.variable to pick the instance as the namespace. You’ll note that self is an argument to every class member function, making it part of the local namespace.

See Python Scope Rules, Python Scope, Variable Scope.


回答 6

在哪里找到x?

找不到x,因为您尚未定义x。:-)如果将其放在代码1(全局)或代码3(本地)中,则可以找到它。

code2(类成员)对于相同类的方法内部的代码不可见-您通常可以使用self来访问它们。code4 / code5(循环)的作用域与code3相同,因此,如果您在其中写入x,则将更改code3中定义的x实例,而不创建新的x。

Python是静态作用域的,因此,如果您将“垃圾邮件”传递给另一个函数,则垃圾邮件仍可访问其来源模块(在code1中定义)以及其他任何包含作用域的模块中的全局变量(请参见下文)。code2成员将再次通过self访问。

lambda和def一样。如果在函数内部使用了lambda,则与定义嵌套函数相同。从Python 2.2开始,可以使用嵌套作用域。在这种情况下,您可以在函数嵌套的任何级别绑定x,Python将选择最里面的实例:

x= 0
def fun1():
    x= 1
    def fun2():
        x= 2
        def fun3():
            return x
        return fun3()
    return fun2()
print fun1(), x

2 0

fun3从最近的包含范围(与fun2关联的函数范围)中看到实例x。但是在fun1和全局中定义的其他x实例不受影响。

在nested_scopes之前(在Python 2.1之前的版本中以及在2.1中,除非您专门使用from-future-import要求功能),fun3不可见fun1和fun2的作用域,因此S.Lott的答案成立,您将获得全局x :

0 0

Where is x found?

x is not found as you haven’t defined it. :-) It could be found in code1 (global) or code3 (local) if you put it there.

code2 (class members) aren’t visible to code inside methods of the same class — you would usually access them using self. code4/code5 (loops) live in the same scope as code3, so if you wrote to x in there you would be changing the x instance defined in code3, not making a new x.

Python is statically scoped, so if you pass ‘spam’ to another function spam will still have access to globals in the module it came from (defined in code1), and any other containing scopes (see below). code2 members would again be accessed through self.

lambda is no different to def. If you have a lambda used inside a function, it’s the same as defining a nested function. In Python 2.2 onwards, nested scopes are available. In this case you can bind x at any level of function nesting and Python will pick up the innermost instance:

x= 0
def fun1():
    x= 1
    def fun2():
        x= 2
        def fun3():
            return x
        return fun3()
    return fun2()
print fun1(), x

2 0

fun3 sees the instance x from the nearest containing scope, which is the function scope associated with fun2. But the other x instances, defined in fun1 and globally, are not affected.

Before nested_scopes — in Python pre-2.1, and in 2.1 unless you specifically ask for the feature using a from-future-import — fun1 and fun2’s scopes are not visible to fun3, so S.Lott’s answer holds and you would get the global x:

0 0

回答 7

在Python中,

分配了值的任何变量对于分配在其中出现的块都是局部的。

如果在当前范围内找不到变量,请参考LEGB顺序。

In Python,

any variable that is assigned a value is local to the block in which the assignment appears.

If a variable can’t be found in the current scope, please refer to the LEGB order.