如何使用 Python 代码理解动态范围?

dir*_*obs 1 python scope

我是一名来自 Python 背景的程序员,通常使用词法范围,我想了解动态范围。网上查了下,还是不太明白。例如,我读过这个页面,这让我觉得事情变得容易多了,尤其是代码片段:

#In Dynamic scoping:         
    const int b = 5;        
    int foo()               
    {                       
       int a = b + 5;
       return a;
    }

    int bar()
    {
       int b = 2;
       return foo();
    }

    int main()
    {
       foo(); // returns 10
       bar(); // returns 7
       return 0;
    }


#In lexical scoping:         
    const int b = 5;        
    int foo()               
    {                       
       int a = b + 5;
       return a;
    }

    int bar()
    {
       int b = 2;
       return foo();
    }

    int main()
    {
       foo(); // returns 10
       bar(); // returns 10
       return 0;
    }
Run Code Online (Sandbox Code Playgroud)

正如我所理解的,正如你所看到的,在动态范围内,bar函数返回 7 而不是 10,这意味着foo调用了在b中定义的变量,bar换句话说,foo没有寻找b在代码顶部定义的变量(第一个b 变量),而是使用了bbar.

Q1:因此,在动态范围界定,这就是被称为在这种情况下,另一个函数中的函数foo调用bar首先查找在这种情况下,调用函数的变量bar ,然后查找顶层的变量?

Q2:你能解释一下 Python 代码中的动态作用域吗?

Mar*_*ers 8

Python 中没有动态范围,除非您实现自己的基于堆栈的 'namespace'

是的,动态范围就是这么简单;变量的值由最近的调用命名空间决定的值由设置值确定。把调用看成一个栈,通过从上到下搜索当前调用栈来查找一个值。

因此,对于您的动态示例,堆栈首先是:

foo
main 
globals -> b = 5
Run Code Online (Sandbox Code Playgroud)

查找b = 5堆栈时查找,然后堆栈更改为

foo
bar -> b = 2
main
globals -> b = 5
Run Code Online (Sandbox Code Playgroud)

所以b = 2被发现。

  • Python 的[上下文变量](https://docs.python.org/3/library/contextvars.html) (3.7) 不只是动态范围的变量吗? (2认同)