python:绑定如何工作

发布于 2024-10-04 21:46:23 字数 613 浏览 3 评论 0原文

我想了解 python 中的变量绑定到底是如何工作的。让我们看看这个:

def foo(x):
    def bar():
        print y
    return bar

y = 5
bar = foo(2)
bar()

这打印了 5,这对我来说似乎是合理的。

def foo(x):
    def bar():
        print x
    return bar
x = 5
bar = foo(2)
bar()

这会打印 2,这很奇怪。在第一个示例中,python 在执行期间查找变量,在第二个示例中,则在创建方法时查找变量。为什么会这样呢?

需要明确的是:这非常酷并且完全按照我的意愿工作。但是,我对内部 bar 函数如何获取其上下文感到困惑。我想了解幕后发生了什么。

编辑

我知道,局部变量具有更高的优先级。我很好奇,python 如何知道在执行过程中从我之前调用过的函数中获取参数。 bar 是在 foo 中创建的,而 x 已不存在。创建函数时是否已将此 x 绑定到参数值?

I am trying to understand, how exactly variable binding in python works. Let's look at this:

def foo(x):
    def bar():
        print y
    return bar

y = 5
bar = foo(2)
bar()

This prints 5 which seems reasonable to me.

def foo(x):
    def bar():
        print x
    return bar
x = 5
bar = foo(2)
bar()

This prints 2, which is strange. In the first example python looks for the variable during execution, in the second when the method is created. Why is it so?

To be clear: this is very cool and works exactly as I would like it to. However, I am confused about how internal bar function gets its context. I would like to understand, what happens under the hood.

EDIT

I know, that local variables have greater priority. I am curious, how python knows during execution to take the argument from a function I have called previously. bar was created in foo and x is not existing any more. It have bound this x to the argument value when function was created?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白云不回头 2024-10-11 21:46:28

这是作用域的问题,第二个示例使用局部作用域变量 x,即上面全局声明的变量

It is mater of scope, second example uses local scope variable x, that is preceded above globally declared

橘和柠 2024-10-11 21:46:27

在这两个示例中,查找都在运行时发生。唯一的区别是有一个本地定义的变量x,而没有本地定义的变量y

当执行……时

def foo(x):
    def bar():
        print y

    return bar

y = 5
bar = foo(2)
bar()

print语句查找名为y的变量,并且只在全局上下文中找到它,因此它使用该变量,并打印“ 5”。

在......

def foo(x):
    def bar():
        print x

    return bar

x = 5
bar = foo(2)
bar()

当查找发生时,定义了一个作用域变量x——当foo时,它被固定为“5” code> 函数被调用。

关键是参数在传递给函数时进行求值,因此外部函数 foo 会在调用时对传入的参数进行求值。这实际上在 foo 函数的上下文中创建了一个名为 x 的变量,因此每当 bar 执行时,它都会看到该变量,而不是全局定义的变量一。

这有时会令人困惑,如以下代码所示:

lst = []
for i in range(5):
    x = i
    lst.append(lambda: x)

for func in lst:
    print func()  # prints 4 4 4 4 4

您需要执行以下操作:

lst = []
for i in range(5):
    def _func(x):
        return lambda: x

    lst.append(_func(i))

for func in lst:
    print func()  # prints 0 1 2 3 4

In both examples, the lookup happens at runtime. The only difference is that there's a locally defined variable x, while there isn't a locally defined variable y.

When executing ...

def foo(x):
    def bar():
        print y

    return bar

y = 5
bar = foo(2)
bar()

... the print statement looks up the variable named y, and only finds it in the global context, so it uses that one, and prints "5".

In ...

def foo(x):
    def bar():
        print x

    return bar

x = 5
bar = foo(2)
bar()

... when the lookup occurs, there is a scoped variable x defined--which is fixed at "5" when the foo function is called.

The key is that arguments are evaluated at the time they're passed into functions, so the outer function foo evaluates the arguments passed in when it's called. This effectively creates a variable called x in the context of the foo function, so whenever bar executes it sees that variable, and not the globally defined one.

This can occasionally be confusing, as in the following code:

lst = []
for i in range(5):
    x = i
    lst.append(lambda: x)

for func in lst:
    print func()  # prints 4 4 4 4 4

You need to do:

lst = []
for i in range(5):
    def _func(x):
        return lambda: x

    lst.append(_func(i))

for func in lst:
    print func()  # prints 0 1 2 3 4
云柯 2024-10-11 21:46:27

没什么奇怪的,这是因为函数参数中的“x”比全局变量“x”具有更高的优先级。

首先,全局变量是一个大祸害。

Python 有“global”运算符:

>>> def foo(x):
...     def bar():
...          global x
...          print x
...     return bar
... 
>>> x = 5
>>> bar = foo(2)
>>> bar()
5

Nothing strange, it is because "x" from function argument has higher priority than global variable "x".

At first, global variables is a great evil.

Python has operator "global":

>>> def foo(x):
...     def bar():
...          global x
...          print x
...     return bar
... 
>>> x = 5
>>> bar = foo(2)
>>> bar()
5
仙气飘飘 2024-10-11 21:46:26

第二个示例实现了所谓的闭包。函数bar 从其周围上下文(即函数foo)引用变量x。这先于对全局变量 x 的引用。

另请参阅这个问题 你能解释一下闭包吗(因为它们与 Python 相关) )?

The second example implements what is called a closure. The function bar is referencing the variable x from its surrounding context, i.e. the function foo. This precedes the reference to the global variable x.

See also this question Can you explain closures (as they relate to Python)?

无远思近则忧 2024-10-11 21:46:26

您提到的问题是 python 中变量的词法作用域与动态作用域之一。明确地说,Python 定义了以下四个作用域。

  1. 首先搜索的最内层作用域包含局部名称。
  2. 从最近的封闭作用域开始搜索的任何封闭函数的作用域包含非局部名称,但也包含非全局名称。
  3. 倒数第二个作用域包含当前模块的全局名称
  4. 最外层作用域(最后搜索)是包含内置名称的命名空间

在第一个示例中,其中“y”在函数栏之外定义,python 搜索最内层作用域并沿链向上移动,直到找到模块中的全局变量“y”

在第二个示例中,其中“x”由函数 foo(x) 定义,当 x 被打印在 bar 内时,x 属于封闭函数的范围。纯粹来说,已经定义了闭包。

为了进一步研究 python 中的作用域,我发现了以下 文章读得很好

The issue that you are alluding to is one of lexical vs dynamic scoping of variables in python. To be explicit, python defines the following four scopes.

  1. The innermost scope, which is searched first, contains the local names
  2. The scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
  3. the next-to-last scope contains the current module’s global names
  4. the outermost scope (searched last) is the namespace containing built-in names

In the first example, where "y" is defined outside of the function bar, python searched for the innermost scope and moved up the chain until it found the global variable "y" in the module

In the second example, where "x" is being defined by function foo(x), x belongs to the scope of an enclosing function, when its being printed inside bar. In pure terms, a closure has been defined.

For further study on scoping in python, I found the following article a great read

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文