Kā lietot lambda funkcijas Python
Lambda funkcijas ir bijušas funkcionālās programmēšanas metode kopš Python 1.0. Tomēr pēdējos gados citas metodes ir ieguvušas lielāku popularitāti un lielā mērā aizstājušas lambdas. Tomēr joprojām ir daži specializēti lambdas lietojumi, par kuriem pieredzējušiem Python programmētājiem būtu jāzina.
Kas ir lambda funkcijas Python?
Python valodā lambda funkcija attiecas uz anonīmu funkciju. Python izmanto atslēgvārdu lambda, lai izveidotu lambda funkciju. Lambda izteiksme sastāv no atslēgvārda lambda, kam seko argumentu saraksts, defise un viens izteiksmes elements. Izteiksme tiek nodrošināta ar argumentiem un izvērtēta, kad tiek izsaukta lambda funkcija:
lambda argument: expressionFunkcijas ir gandrīz katras programmēšanas valodas pamatkonstrukcija, un tās ir mazākās atkārtoti izmantojamās koda vienības. Parasti funkcijas Python valodā tiek definētas ar atslēgvārdu def. Kā piemēru parādīsim kvadrāta funkciju, kas reizinā skaitli ar sevi:
# Define square function
def square(num):
return num * num
# Show that it works
assert square(9) == 81pythondef atslēgvārds ir labi pazīstams veids, kā definēt funkcijas Python, bet šajā valodā ir arī lambdas. Tās ir anonīmas funkcijas, kas definē izteiksmi ar parametriem. Lambdas var izmantot visur, kur ir nepieciešama funkcija vai kur to var piešķirt vārdam. Šeit var redzēt lambda izteiksmi, kas atbilst kvadrāta funkcijai:
# Create square function
squared = lambda num: num * num
# Show that it works
assert squared(9) == 81pythonKāda ir atšķirība starp lambda un def?
Var šķist dīvaini, ka Python ļauj izveidot funkcijas gan ar lambda, gan ar def. Tomēr Lambda nav tā paša funkcija, bet gan tikai vēl viens veids, kā izveidot īsas funkcijas lokāli. Katru funkciju, kas izveidota ar lambda, var izveidot arī ar def. Tomēr otrādi tas tā nav.
Sintaktiskā līmenī lambda un def ir abi atslēgvārdi. Viena no galvenajām atšķirībām starp tiem ir Python stingrā izteikumu un izteiksmes nošķiršana. Izteikumi ir soļi koda izpildē, bet izteiksmes tiek novērtētas kā vērtība.
Def sāk paziņojumu, vai, precīzāk , salikto paziņojumu, kas satur turpmākus paziņojumus. def paziņojumā var parādīties tikai return paziņojums. return paziņojums atgriež vērtību, kad tiek izsaukta ar def definētā funkcija.
Atšķirībā no def izteikuma, lambda sāk izteikumu, kas nevar saturēt nekādus izteikumus. Lambda izteikums pieņem vienu vai vairākus argumentus un atgriež anonīmu funkciju. Kad tiek izsaukta lambda funkcija, tajā ietvertais izteikums tiek izvērtēts ar nodotajiem argumentiem un atgriezts.
Kādi ir Python lambda izteikumu ierobežojumi?
Python ir apzināti ierobežojis lambda funkciju lietderību, jo parasti ir labāk nosaukt funkcijas. Tas liek programmētājiem domāt par funkcijas nozīmi un skaidri nošķirt tās daļas.
Lambdas nevar saturēt instrukcijas, atšķirībā no funkcijas ķermeņa, kas definēts ar atslēgvārdu def. Tāpēc lambda funkcijā nav iespējams izmantot if, for utt. Nav iespējams arī izraisīt izņēmumu, jo tam nepieciešama raise instrukcija.
Lambda funkcijas Python var saturēt vienu izteiksmi, kas tiek izvērtēta, kad tā tiek izsaukta. Lambda izteiksmes ietvaros nevar izmantot tipa anotācijas. Mūsdienās lielākajā daļā Python lambda funkciju lietošanas gadījumu tiek izmantotas citas metodes, piemēram, izpratne.
Lambda funkciju dažādi lietojumi Python valodā
Lambda ir atvasinātas no funkcionālās programmēšanas. Dažās valodās, piemēram, JavaScript, anonīmas funkcijas tiek plaši izmantotas bez nepieciešamības pēc īpašas atslēgvārda. Python valodā lambda izteiksmes tiek izmantotas, lai lokāli izveidotu nelielas funkcijas. Turpinājumā apskatīsim to visnoderīgākos pielietojumus.
Kā aizpildīt augstākas kārtas funkcijas Python ar lambdas
Lambdas bieži tiek izmantotas ar augstākas kārtas funkcijām, piemēram, map(), filter() un reduce(). Iterējamo elementus var pārveidot bez cilpu izmantošanas, pateicoties lambdas. Augstākas kārtas funkcijas ir funkcijas, kas kā parametrus izmanto funkcijas vai atgriež funkciju.
Funkcija map() kā parametrus pieņem funkciju un iterējamu objektu. Tā izpilda funkciju katram iterējama objekta elementam. Pamēģināsim ģenerēt kvadrātskaitļus. Mēs izmantojam funkciju map() un kā argumentu nododam lambda izteiksmi, kas ģenerē kvadrāta funkciju. Kvadrāta funkcija tiek piemērota katram saraksta elementam ar map():
nums = [3, 5, 7]
# Square numbers using `map()` and `lambda`
squares = map(lambda num: num ** 2, nums)
# Show that it works
assert list(squares) == [9, 25, 49]pythonSākot ar Python 3.0, funkcijas map() un filter() atgriež iterējamu objektu, nevis sarakstu. list() izsaukums tiek izmantots assert izteikumos, lai izpakotu iterējamus objektus sarakstā.
Saraksta izpratne piedāvā modernāku pieeju iterējamo objektu apstrādei. Tā vietā, lai izmantotu map() un ģenerētu lambda funkciju, mēs varam aprakstīt operāciju tieši:
nums = [3, 5, 7]
# Square numbers using list comprehension
squares = [num ** 2 for num in nums]
# Show that it works
assert squares == [9, 25, 49]pythonFunkciju filter() var izmantot, lai filtrētu iterējamas struktūras elementus. Mēs varam paplašināt mūsu piemēru, lai ģenerētu tikai pāra kvadrātskaitļus:
# List of numbers 1-4
nums = [1, 2, 3, 4]
# Square each number
squares = list(map(lambda num: num ** 2, nums))
# Filter out the even squares
even_squares = filter(lambda square: square % 2 == 0, squares)
# Show that it works
assert list(even_squares) == [4, 16]pythonMēs parādām vēlamo pieeju, izmantojot saraksta izpratni, lai iegūtu to pašu rezultātu, neizmantojot lambdas un augstākas kārtas funkcijas. Izpratnes if daļa tiek izmantota, lai atlasītu pāra skaitļus no ģenerētajiem kvadrātskaitļiem:
# List of numbers 1-4 squared
squares = [num ** 2 for num in range(1, 5)]
# Filter out the even squares
even_squares = [square for square in squares if square % 2 == 0]
# Show that it works
assert even_squares == [4, 16]pythonPython reduce() funkcija nav iekļauta standarta bibliotēkā kopš Python 3.0 versijas. Šo funkciju var atrast functools modulī.
Kā īstenot galvenās funkcijas Python ar lambdas
Comprehensions ir lielā mērā aizstājušas klasiskās augstākas kārtas funkcijas map() un filter() Python. Tomēr galvenās funkcijas var izmantot, lai parādītu lambda pilnīgo potenciālu.
Python salīdzināšanas funkcijas sorted(), min() un max() darbojas ar iterējamiem objektiem. Katrs iterējama objekta elements tiek salīdzināts, kad tiek izsaukta funkcija. Trīs funkcijas pieņem atslēgas funkciju kā neobligātu key parametru. Atslēgas funkcija tiek izsaukta katram elementam un atgriež atslēgas vērtību salīdzināšanas operācijai.
Apsveriet šādu problēmu. Mums ir mape ar attēlu failiem, kuru nosaukumi ir saistīti ar Python sarakstu. Mēs vēlamies šo sarakstu sakārtot. Visi failu nosaukumi sākas ar img, kam seko skaitlis:
# List of image file names
images = ['img1', 'img2', 'img30', 'img3', 'img22', 'img100']pythonJa izmantojam Python sorted() funkciju, tiek izmantota leksikogrāfiskā secība. Tā secīgus ciparus uzskata par atsevišķiem skaitļiem. Tādējādi skaitļi ['1', '2', '100'] tiek sakārtoti secībā ['1', '100', '2']. Rezultāts nav tāds, kādu gaidījām:
# Sort using lexicographic order
sorted_image = sorted(images)
# Show that it works
assert sorted_image == ['img1', 'img100', 'img2', 'img22', 'img3', 'img30']pythonMēs nododam lambda izteiksmi, kas rada atslēgas funkciju, lai nodrošinātu pareizu šķirošanu. Atslēgas funkcija izgūst faila nosaukuma ciparu daļu, ko sorted() izmanto kā atslēgu:
# Extract numeric component and sort as integers
sorted_image = sorted(images, key=lambda name: int(name[3:]))
# Show that it works
assert sorted_image == ['img1', 'img2', 'img3', 'img22', 'img30', 'img100']pythonGalvenā funkcija tiek izmantota lokāli un tikai vienu reizi. Nav nepieciešams definēt papildu nosaukumu tai. Lambdas ir pareizais veids, kā izveidot galvenās funkcijas. Apskatīsim vēl divus piemērus.
Tāpat kā sorted(), arī iebūvētās Python funkcijas min() un max() pieņem fakultatīvu atslēgas funkciju. Funkcijas atrod mazāko un lielāko elementu sarakstā vai citā iterējamā objektā. Mazākais vai lielākais elements ir definīcijas jautājums un to var norādīt, izmantojot atslēgas funkciju.
Ir skaidrs, ko nozīmē mazākais vai lielākais elements vienkāršu vērtību sarakstos, piemēram, skaitļu sarakstā. Šajā gadījumā mums nav nepieciešama īpaša atslēgas funkcija:
nums = [42, 69, 51, 13]
assert min(nums) == 13
assert max(nums) == 69pythonJa netiek nodota neviena atslēgas funkcija, kā noklusējuma funkcija tiek izmantota identitātes funkcija f(x) = x. To var viegli definēt kā Python lambda ar lambda x: x.
Bet kas notiek, ja katrs iterējama elementa elements ietver vairākus datumus? Iedomāsimies sarakstu ar vārdnīcām, kas attēlo cilvēkus ar viņu vārdiem un vecumu. Kāds ir kritērijs min() un max() gadījumā, lemjot, kurš ir mazākais un kurš lielākais elements? Šeit noderīga ir atslēgas funkcija.
Mums ir nepieciešami parauga dati, lai ilustrētu, kā darbojas galvenās funkcijas. Izveidosim funkciju Person(), kas kalpos kā konstruktors:
# Constructor function for dict representing a person
def Person(name, age):
return {'name': name, 'age': age}
# Check that it works as expected
assert Person('Jim', 42) == {'name': 'Jim', 'age': 42}pythonMēs izveidojam cilvēku sarakstu, izmantojot mūsu konstruktora funkciju:
# Create list of people
people = [person('Jim', 42), person('Jack', 51), person('John', 69)]pythonMēs atrodam vecāko personu, izmantojot max() izsaukumu. Tas ģenerē atslēgas funkciju, izmantojot lambda izteiksmi, kas ņem personas diktu un izgūst no tā vecumu kā salīdzināšanas elementu:
# Find the oldest person
oldest = max(people, key=lambda person: person['age'])
# Check that it works
assert oldest == Person('John', 69)pythonŠī pieeja darbojas tieši tāpat arī min() funkcijā. Šajā gadījumā mēs definēsim galveno funkciju ārpus min() izsaukuma un atkal izmantosim lambda izteiksmi. Tas uzlabo lasāmību un ir lietderīgi, ja galvenajai funkcijai ir vairāki vietējie lietojumi:
# Define key function to compare people by age
by_age = lambda person: person['age']
# Find the youngest person
youngest = min(people, key=by_age)
# Check that it works
assert youngest == Person('Jim', 42)pythonKā izveidot slēgumus ar Python lambdas
Python lambdas tiek izmantotas arī, definējot slēgumus. Tās ir funkcijas, kuras izveido citas funkcijas un kuras glabā vērtību. Slēgumus var izmantot, lai izveidotu līdzīgu funkciju grupas. Parādīsim tipisku piemēru, kurā tiek izveidotas potences funkcijas.
Potenču funkcijas pieņem argumentu un to eksponenciāli aprēķina. Kvadrāta funkcija f(x) = x ^ 2 un kubiska funkcija f(x) = x ^ 3 ir labi zināmi piemēri. Jebkuras potences funkcijas var ģenerēt kā slēgumus, izmantojot konstruktora funkciju. Mēs izmantosim lambda izteiksmi, kas nozīmē, ka mums nav jādefinē iekšējā nosaukta funkcija:
# Define constructor function for power functions
def power(n):
return lambda num: num ** n
# Create square and cubic functions as closures
square = power(2)
cubic = power(3)
# Show that it works
assert square(10) == 100
assert cubic(10) == 1000pythonKā izmantot nekavējoties izsaukto funkciju izteiksmi (IIFE) ar Python lambdas
IIFE, izrunā kā „iffy”, ir pazīstams modelis JavaScript. Tas ietver anonīmas funkcijas definēšanu un tās tūlītēju izpildi.
Lambda var izmantot kā IIFE, lai gan tās nav īpaši noderīgas Python ierobežojumu dēļ. Mums tikai jāievieto lambda izteiksme iekavās:
(lambda num: num * num)pythonUn vēl viena pāri iekavās, kas satur argumentu(-us):
assert (lambda num: num * num)(3) == 9python