lambda函数不使用localmost scop

2024-03-28 11:33:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一个简短的代码来处理一个数据文件,但在lambda函数的工作方式中,我偶然发现了一些我不理解的东西。你知道吗

问题是:我有一个关键字列表,以及那些关键字出现在数据文件中的行的索引列表,并且希望对所述行应用某些操作(和/或相邻行,因此需要索引列表,而不仅仅是行列表)。你知道吗

为此,我定义了一个字典,将每个关键字与lambda函数相关联,lambda函数将所需操作应用于所需行。例如:

methnames = {'acell'     : lambda i : float(dat[i][1])  } #with dat the data file

(除了多个关键字和更复杂的函数)。你知道吗

现在,如我所料,为了执行它,需要定义一个名为dat的全局变量,所以我只放了一个dat=[],因为我会在定义dat的局部范围内调用这些函数。你知道吗

除了在执行整个代码时,我得到一个IndexError,回溯告诉我,即使lambda确实是从通常应该定义dat的本地范围内调用的,它仍然使用全局dat。你知道吗

即使我可以绕过它,这对于Python来说似乎是一个非常奇怪的行为,所以我可能遗漏了一些东西。你知道吗

以下是代码的简化版本:

dat=[]
methnames = {'acell'     : lambda i : float(dat[i][1])  }

def test(dat):
    return(methnames['acell'](0))

 a=test([['acell',0,1,1]])

它通常会给出a=0,下面是回报:

Traceback (most recent call last):

  File "<ipython-input-21-cc8eb6df810c>", line 1, in <module>
runfile('/home/penwwern/Documents/mineralo/MinPhys/FrI/out/test.py', wdir='/home/penwwern/Documents/mineralo/MinPhys/FrI/out')

  File "/usr/lib/python3/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 699, in runfile
execfile(filename, namespace)

  File "/usr/lib/python3/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 88, in execfile
exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "/home/penwwern/Documents/mineralo/MinPhys/FrI/out/test.py", line 18, in <module>
a=test([['acell',0,1,1]])

  File "/home/penwwern/Documents/mineralo/MinPhys/FrI/out/test.py", line 15, in test
    return(methnames['acell'](0))

  File "/home/penwwern/Documents/mineralo/MinPhys/FrI/out/test.py", line 9, in <lambda>
    methnames = {'acell'     : lambda i : float(dat[i][1])  }

IndexError: list index out of range

Tags: lambda函数inpytesthomelineout
1条回答
网友
1楼 · 发布于 2024-03-28 11:33:37

Python不检查调用方的作用域,而是检查函数的定义位置。这是因为Python is lexically scoped。你知道吗

In [1]: def f(): print(i)

In [2]: def f2():
   ...:     i = 10
   ...:     f()
   ...:

In [3]: f2()
                                     -
NameError                                 Traceback (most recent call last)
<ipython-input-3-fdec4c1c071f> in <module>()
  > 1 f2()

<ipython-input-2-5ab58f8d1867> in f2()
      1 def f2():
      2     i = 10
  > 3     f()
      4

<ipython-input-1-a5bb8b95e798> in f()
  > 1 def f(): print(i)
NameError: name 'i' is not defined

现在,我们可以在定义f的相同范围内绑定i

In [4]: i = 88

In [5]: f2()
88

但是,它会检查封闭作用域的定义位置:

In [6]: def f3():
   ...:     i = 1
   ...:     def inner():
   ...:         print(i)
   ...:     return inner
   ...:

In [7]: inner = f3()

In [8]: inner()
1

In [9]: print(i)
88

词汇范围界定是很常见的。以下是来自维基百科的更多信息:

A fundamental distinction in scoping is what "part of a program" means. In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined. In contrast, in languages with dynamic scope the name resolution depends upon the program state when the name is encountered which is determined by the execution context or calling context. In practice, with lexical scope a variable's definition is resolved by searching its containing block or function, then if that fails searching the outer containing block, and so on, whereas with dynamic scope the calling function is searched, then the function which called that calling function, and so on, progressing up the call stack.[4] Of course, in both rules, we first look for a local definition of a variable.

https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope_vs._dynamic_scope

相关问题 更多 >