ตัวดำเนินการนิพจน์การกำหนดที่:=
เพิ่มใน Python 3.8สนับสนุนการกำหนดภายในของนิพจน์แลมบ์ดา ตัวดำเนินการนี้สามารถปรากฏภายในนิพจน์(...)
วงเล็บวงเล็บ[...]
หรือวงเล็บปีกกาเท่านั้น{...}
เนื่องจากเหตุผลทางวากยสัมพันธ์ ตัวอย่างเช่นเราจะสามารถเขียนสิ่งต่อไปนี้:
import sys
say_hello = lambda: (
message := "Hello world",
sys.stdout.write(message + "\n")
)[-1]
say_hello()
ใน Python 2 เป็นไปได้ที่จะดำเนินการมอบหมายภายในเครื่องซึ่งเป็นผลข้างเคียงของความเข้าใจในรายการ
import sys
say_hello = lambda: (
[None for message in ["Hello world"]],
sys.stdout.write(message + "\n")
)[-1]
say_hello()
อย่างไรก็ตามคุณไม่สามารถใช้สิ่งเหล่านี้ในตัวอย่างของคุณได้เนื่องจากตัวแปรของคุณflag
อยู่ในขอบเขตภายนอกไม่ใช่lambda
ขอบเขตของ สิ่งนี้ไม่เกี่ยวข้องกับlambda
มันเป็นพฤติกรรมทั่วไปใน Python 2 Python 3 ช่วยให้คุณสามารถแก้ปัญหานี้ด้วยnonlocal
คีย์เวิร์ดภายในdef
s แต่nonlocal
ไม่สามารถใช้ภายในlambda
s ได้
มีวิธีแก้ปัญหาชั่วคราว (ดูด้านล่าง) แต่ในขณะที่เราอยู่ในหัวข้อ ...
ในบางกรณีคุณสามารถใช้สิ่งนี้เพื่อทำทุกอย่างภายใน a lambda
:
(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()])()
ทรงกระบอกที่มีรัศมี 10.0 ซม. และสูง 20.0 ซม. มีปริมาตร 6283.2 ซม. ³
ทรงกระบอกที่มีรัศมี 20.0 ซม. และสูง 40.0 ซม. มีปริมาตร 50265.5 ซม.
ทรงกระบอกที่มีรัศมี 30.0 ซม. และสูง 60.0 ซม. มีปริมาตร 169646.0 ซม.
กรุณาอย่า
... กลับไปที่ตัวอย่างเดิมของคุณ: แม้ว่าคุณจะไม่สามารถทำการกำหนดให้กับflag
ตัวแปรในขอบเขตภายนอกได้ แต่คุณสามารถใช้ฟังก์ชันเพื่อแก้ไขค่าที่กำหนดไว้ก่อนหน้านี้ได้
ตัวอย่างเช่นflag
อาจเป็นวัตถุที่.value
เราตั้งค่าโดยใช้setattr
:
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)
[Object(name=''), Object(name='fake_name')]
หากเราต้องการให้เข้ากับธีมข้างต้นเราสามารถใช้การทำความเข้าใจรายการแทนsetattr
:
[None for flag.value in [bool(o.name)]]
แต่จริงๆแล้วในโค้ดที่จริงจังคุณควรใช้คำจำกัดความของฟังก์ชันปกติแทนlambda
ถ้าคุณกำลังจะทำการมอบหมายภายนอก
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)