<p><a href="https://www.python.org/dev/peps/pep-0572/" rel="noreferrer">The assignment expression operator ^{<cd1>} added in Python 3.8</a>支持lambda表达式内部的赋值。出于语法原因,此运算符只能出现在带括号的<code>(...)</code>、带括号的<code>[...]</code>或带括号的<code>{...}</code>表达式中。例如,我们将能够编写以下内容:</p>
<pre class="lang-python prettyprint-override"><code>import sys
say_hello = lambda: (
message := "Hello world",
sys.stdout.write(message + "\n")
)[-1]
say_hello()
</code></pre>
<p>在Python 2中,作为列表理解的副作用,可以执行本地赋值。</p>
<pre class="lang-python prettyprint-override"><code>import sys
say_hello = lambda: (
[None for message in ["Hello world"]],
sys.stdout.write(message + "\n")
)[-1]
say_hello()
</code></pre>
<p>但是,在您的示例中不可能使用这两种方法,因为变量<code>flag</code>位于外部作用域中,而不是<code>lambda</code>的作用域中。这与<code>lambda</code>无关,这是Python 2中的一般行为。Python 3允许您在<code>def</code>s内部使用<code>nonlocal</code>关键字来解决这个问题,但是<code>nonlocal</code>不能在<code>lambda</code>s内部使用</p>
<p>有一个解决办法(见下文),但当我们讨论这个话题时。。。</p>
<hr/>
<p>在某些情况下,您可以使用它来执行<code>lambda</code>中的所有操作:</p>
<pre class="lang-python prettyprint-override"><code>(lambda: [
['def'
for sys in [__import__('sys')]
for math in [__import__('math')]
for sub in [lambda *vals: None]
for fun in [lambda *vals: vals[-1]]
for echo in [lambda *vals: sub(
sys.stdout.write(u" ".join(map(unicode, vals)) + u"\n"))]
for Cylinder in [type('Cylinder', (object,), dict(
__init__ = lambda self, radius, height: sub(
setattr(self, 'radius', radius),
setattr(self, 'height', height)),
volume = property(lambda self: fun(
['def' for top_area in [math.pi * self.radius ** 2]],
self.height * top_area))))]
for main in [lambda: sub(
['loop' for factor in [1, 2, 3] if sub(
['def'
for my_radius, my_height in [[10 * factor, 20 * factor]]
for my_cylinder in [Cylinder(my_radius, my_height)]],
echo(u"A cylinder with a radius of %.1fcm and a height "
u"of %.1fcm has a volume of %.1fcm³."
% (my_radius, my_height, my_cylinder.volume)))])]],
main()])()
</code></pre>
<blockquote>
<p>A cylinder with a radius of 10.0cm and a height of 20.0cm has a volume of 6283.2cm³.<br/>
A cylinder with a radius of 20.0cm and a height of 40.0cm has a volume of 50265.5cm³.<br/>
A cylinder with a radius of 30.0cm and a height of 60.0cm has a volume of 169646.0cm³.</p>
</blockquote>
<p>请不要</p>
<hr/>
<p>…回到原来的示例:虽然不能对外部作用域中的<code>flag</code>变量执行赋值,但可以使用函数修改先前赋值。</p>
<p>例如,<code>flag</code>可以是我们使用<a href="http://docs.python.org/2/library/functions.html#setattr" rel="noreferrer">^{<cd16>}</a>设置其<code>.value</code>的对象:</p>
<pre class="lang-python prettyprint-override"><code>flag = Object(value=True)
input = [Object(name=''), Object(name='fake_name'), Object(name='')]
output = filter(lambda o: [
flag.value or bool(o.name),
setattr(flag, 'value', flag.value and bool(o.name))
][0], input)
</code></pre>
<pre class="lang-none prettyprint-override"><code>[Object(name=''), Object(name='fake_name')]
</code></pre>
<p>如果我们想符合上述主题,可以使用列表理解而不是<code>setattr</code>:</p>
<pre class="lang-python prettyprint-override"><code> [None for flag.value in [bool(o.name)]]
</code></pre>
<hr/>
<p>但实际上,在严肃的代码中,如果要执行外部赋值,则应该始终使用正则函数定义,而不是<code>lambda</code>。</p>
<pre class="lang-python prettyprint-override"><code>flag = Object(value=True)
def not_empty_except_first(o):
result = flag.value or bool(o.name)
flag.value = flag.value and bool(o.name)
return result
input = [Object(name=""), Object(name="fake_name"), Object(name="")]
output = filter(not_empty_except_first, input)
</code></pre>