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 flag
berada di lingkup luar, bukan lambda
cakupannya. Ini tidak ada hubungannya dengan lambda
, ini adalah perilaku umum dalam Python 2. Python 3 memungkinkan Anda menyiasati ini dengan nonlocal
kata kunci di dalam def
s, tetapi nonlocal
tidak dapat digunakan di dalam lambda
s.
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 flag
variabel di lingkup luar, Anda dapat menggunakan fungsi untuk mengubah nilai yang ditetapkan sebelumnya.
Misalnya, flag
bisa menjadi objek yang .value
kita 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 lambda
jika 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)