cos*_*uke 13 python functional-programming python-3.x
在为Bayes'Nets程序实现"变量消除"算法的过程中,我遇到了一个意外的错误,这是一系列对象的迭代映射转换的结果.
为简单起见,我将在这里使用类似的代码:
>>> nums = [1, 2, 3]
>>> for x in [4, 5, 6]:
... # Uses n if x is odd, uses (n + 10) if x is even
... nums = map(
... lambda n: n if x % 2 else n + 10,
... nums)
...
>>> list(nums)
[31, 32, 33]
Run Code Online (Sandbox Code Playgroud)
这绝对是错误的结果.由于[4,5,6]包含两个偶数,10
因此每个元素最多应加两次.我在VE算法中也遇到了意想不到的行为,因此我修改它以在每次迭代后将迭代map
器转换为a list
.
>>> nums = [1, 2, 3]
>>> for x in [4, 5, 6]:
... # Uses n if x is odd, uses (n + 10) if x is even
... nums = map(
... lambda n: n if x % 2 else n + 10,
... nums)
... nums = list(nums)
...
>>> list(nums)
[21, 22, 23]
Run Code Online (Sandbox Code Playgroud)
根据我对可迭代的理解,这种修改不应该改变任何东西,但确实如此.显然,在-ed版本中n + 10
,not x % 2
案例的转换应用次数较少list
.
在发现这个错误后,我的贝叶斯网络程序也运行良好,但我正在寻找解释它为何发生的原因.
awe*_*oon 12
答案很简单:在Python 3中map
是一个惰性函数,它返回一个可迭代对象(在Python 2中它返回一个list
).让我为你的例子添加一些输出:
In [6]: nums = [1, 2, 3]
In [7]: for x in [4, 5, 6]:
...: nums = map(lambda n: n if x % 2 else n + 10, nums)
...: print(x)
...: print(nums)
...:
4
<map object at 0x7ff5e5da6320>
5
<map object at 0x7ff5e5da63c8>
6
<map object at 0x7ff5e5da6400>
In [8]: print(x)
6
In [9]: list(nums)
Out[9]: [31, 32, 33]
Run Code Online (Sandbox Code Playgroud)
注意In[8]
- 值x
是6.我们也可以转换lambda
函数,传递map
给跟踪值的值x
:
In [10]: nums = [1, 2, 3]
In [11]: for x in [4, 5, 6]:
....: nums = map(lambda n: print(x) or (n if x % 2 else n + 10), nums)
....:
In [12]: list(nums)
6
6
6
6
6
6
6
6
6
Out[12]: [31, 32, 33]
Run Code Online (Sandbox Code Playgroud)
因为map
是懒惰的,它会评估何时list
被调用.然而,x
is 的值6
就是它产生令人困惑的输出的原因.nums
在循环内部进行评估会产生预期的输出.
In [13]: nums = [1, 2, 3]
In [14]: for x in [4, 5, 6]:
....: nums = map(lambda n: print(x) or (n if x % 2 else n + 10), nums)
....: nums = list(nums)
....:
4
4
4
5
5
5
6
6
6
In [15]: nums
Out[15]: [21, 22, 23]
Run Code Online (Sandbox Code Playgroud)
问题与x
您正在创建的lambda函数如何访问变量有关.Python的作用域的工作方式,lambda函数将x
在调用它们时始终使用外部作用域的最新版本,而不是它们定义时的值.
由于map
是懒惰的,因此直到循环之后才会调用lambda函数(当你map
通过传递它们来使用嵌套的s时list
),因此,它们都使用最后一个x
值.
要使每个lambda函数保存x
定义它们时的值,请x=x
像这样添加:
lambda n, x=x: n if x % 2 else n + 10
Run Code Online (Sandbox Code Playgroud)
这指定了一个参数及其默认值.默认值将在定义lambda时进行计算,因此当稍后调用lambda(没有第二个参数)时,x
表达式内部将是保存的默认值.
归档时间: |
|
查看次数: |
476 次 |
最近记录: |