Python 范围界定规则的简短描述?

Python 范围界定规则的简短描述?,python,scope,dynamic-languages,Python,Scope,Dynamic Languages,Python的作用域规则是什么 如果我有一些代码: code1 class Foo: code2 def spam..... code3 for code4..: code5 x() 在哪里可以找到x?一些可能的选择包括以下列表: 在封闭的源文件中 在类命名空间中 在函数定义中 for循环中的索引变量 在for循环内部 当函数spam被传递到其他地方时,执行过程中还存在上下文。也许通过的方式会有所不同 一定有一个简单的参考或算法。

Python的作用域规则是什么

如果我有一些代码:

code1
class Foo:
   code2
   def spam.....
      code3
      for code4..:
       code5
       x()
在哪里可以找到
x
?一些可能的选择包括以下列表:

  • 在封闭的源文件中
  • 在类命名空间中
  • 在函数定义中
  • for循环中的索引变量
  • 在for循环内部
  • 当函数
    spam
    被传递到其他地方时,执行过程中还存在上下文。也许通过的方式会有所不同


    一定有一个简单的参考或算法。对于中级Python程序员来说,这是一个令人困惑的世界。

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

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

    有两个函数:
    globals
    locals
    向您显示这两个名称空间的内容

    名称空间由包、模块、类、对象构造和函数创建。没有任何其他风格的名称空间

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

    在本例中,Local是方法函数
    Foo.spam
    的主体

    全球是——嗯——全球的

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

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

    在类定义中,名称是类命名空间的一部分<例如,code>code2,必须由类名限定。通常
    Foo.code2
    。但是,
    self.code2
    也可以工作,因为Python对象将包含的类视为一个后备类

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

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

    x在哪里

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

    代码2(类成员)对同一类的方法内部的代码不可见 — 您通常会使用self访问它们。code4/code5(循环)与code3在同一范围内,因此如果您在其中写入x,您将更改code3中定义的x实例,而不是生成新的x

    Python的作用域是静态的,因此如果您将“spam”传递给另一个函数,spam仍然可以访问它来自的模块(在code1中定义)中的全局变量,以及任何其他包含作用域的函数(见下文)。代码2成员将再次通过self访问

    lambda与def没有什么不同。如果在函数中使用lambda,则与定义嵌套函数相同。在Python2.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实例和全局x实例不受影响

    嵌套_作用域之前 — 在Python 2.1之前版本和2.1版本中,除非您特别要求使用将来导入的 — fun1和fun2的作用域对fun3不可见,因此s.Lott的答案成立,您将得到全局x:

    0 0
    

    实际上,Python范围解析的简明规则是。(这些规则特定于变量名,而不是属性。如果引用时没有句点,则适用这些规则。)

    立法局规则

    • Local—在函数(
      def
      lambda
      )中以任何方式分配的名称,且在该函数中未声明为全局名称

    • Enclosing function—在任何和所有静态封闭函数(
      def
      lambda
      )的局部范围内从内部到外部分配的名称

    • Global(模块)-在模块文件的顶层分配的名称,或通过在文件中的
      def
      中执行
      global
      语句分配的名称

    • B内置(Python)-在内置名称模块中预先分配的名称:
      打开
      范围
      语法错误
      ,等等

    那么,在

    code1
    class Foo:
        code2
        def spam():
            code3
            for code4:
                code5
                x()
    
    for
    循环没有自己的命名空间。按照立法顺序,范围将是

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

    code2
    中永远找不到
    x
    (即使在您可能期望的情况下,也请参见或)。

    Python 2.x的范围规则已被删除
    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_var = 4
    def change_global():
        global global_var
        global_var = global_var + 1
    
    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)
    
    >>> [ i for i in range(5) ]
    >>> i
    4
    
    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()
    
    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
    
    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
    
    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.
    
    import __builtin__
    
    print3 = __builtin__.__dict__['print']
    
    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()
    
    ┎ builtins           [print, ...]
    ┗━┱ globals            [some_global]
      ┗━┱ outer_function     [some_local, some_closure]
        ┣━╾ InnerClass         [some_classvar]
        ┗━╾ inner_function     [some_local]
    
    ┎ builtins           [print, ...]
    ┗━┱ globals            [some_global]
      ┗━┱ outer_function     [some_closure]
        ┗━╾ <listcomp>         [comp_local]