Operator ekspresi penugasan yang :=ditambahkan di Python 3.8 mendukung penugasan di dalam ekspresi lambda. Operator ini hanya dapat muncul dalam ekspresi dalam tanda kurung (...), tanda kurung [...], atau tanda kurung {...}untuk alasan sintaksis. Misalnya, kita bisa menulis yang berikut ini:
import sys
say_hello = lambda: (
message := "Hello world",
sys.stdout.write(message + "\n")
)[-1]
say_hello()
Dalam Python 2, dimungkinkan untuk melakukan tugas lokal sebagai efek samping dari pemahaman daftar.
import sys
say_hello = lambda: (
[None for message in ["Hello world"]],
sys.stdout.write(message + "\n")
)[-1]
say_hello()
Namun, tidak mungkin untuk menggunakan salah satu dari ini dalam contoh Anda karena variabel Anda flagberada di lingkup luar, bukan lambdacakupannya. Ini tidak ada hubungannya dengan lambda, ini adalah perilaku umum dalam Python 2. Python 3 memungkinkan Anda menyiasati ini dengan nonlocalkata kunci di dalam defs, tetapi nonlocaltidak dapat digunakan di dalam lambdas.
Ada solusinya (lihat di bawah), tetapi saat kita membahas topik ...
Dalam beberapa kasus, Anda dapat menggunakan ini untuk melakukan semua yang ada di dalam 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()])()
Sebuah silinder dengan jari-jari 10.0cm dan tinggi 20.0cm memiliki volume 6.283.2cm³.
Sebuah silinder dengan jari-jari 20.0cm dan tinggi 40.0cm memiliki volume 50265.5cm³.
Silinder dengan jari-jari 30.0cm dan tinggi 60.0cm memiliki volume 169646.0cm³.
Tolong jangan.
... kembali ke contoh awal Anda: meskipun Anda tidak dapat melakukan tugas ke flagvariabel di lingkup luar, Anda dapat menggunakan fungsi untuk mengubah nilai yang ditetapkan sebelumnya.
Misalnya, flagbisa menjadi objek yang .valuekita atur menggunakan 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')]
Jika kita ingin menyesuaikan tema di atas, kita bisa menggunakan pemahaman daftar alih-alih setattr:
[None for flag.value in [bool(o.name)]]
Tapi sungguh, dalam kode serius Anda harus selalu menggunakan definisi fungsi biasa daripada lambdajika Anda akan melakukan tugas luar.
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)