Kaip naudoti lambda funkcijas Python kalboje
Lambda funkcijos yra funkcinio programavimo metodas nuo Python 1.0 versijos. Tačiau pastaraisiais metais kitos technikos tapo populiaresnės ir iš esmės pakeitė lambda funkcijas. Nepaisant to, vis dar yra keletas specializuotų lambda funkcijų naudojimo atvejų, kuriuos patyrę Python programuotojai turėtų žinoti.
Kas yra lambda funkcijos Python kalboje?
Python kalboje lambda funkcija reiškia anoniminę funkciją. Python naudoja raktinį žodį lambda, kad sukurtų lambda funkciją. Lambda išraiška susideda iš raktinio žodžio lambda, po kurio eina argumentų sąrašas, dvitaškis ir viena išraiška. Išraiška pateikiama su argumentais ir įvertinama, kai iškviečiama lambda funkcija:
lambda argument: expressionFunkcijos yra pagrindinė beveik kiekvienos programavimo kalbos konstrukcija, jos yra mažiausias pakartotinai naudojamas kodo vienetas. Paprastai Python kalboje funkcijos apibrėžiamos naudojant raktinį žodį def. Pateiksime pavyzdį – kvadratinę funkciją, kuri daugina skaičių iš jo paties:
# Define square function
def square(num):
return num * num
# Show that it works
assert square(9) == 81pythondef raktinis žodis yra gerai žinomas būdas apibrėžti funkcijas Python kalboje, tačiau šioje kalboje taip pat yra lambda funkcijos. Tai yra anoniminės funkcijos, kurios apibrėžia išraišką su parametrais. Lambda funkcijos gali būti naudojamos visur, kur tikimasi funkcijos arba kur ji gali būti priskirta vardui. Čia galite pamatyti lambda išraišką, lygią kvadrato funkcijai:
# Create square function
squared = lambda num: num * num
# Show that it works
assert squared(9) == 81pythonKoks yra skirtumas tarp lambda ir def?
Gali atrodyti keista, kad Python leidžia kurti funkcijas tiek su lambda, tiek su def. Tačiau Lambda nėra jo savybė, o tik dar vienas būdas kurti trumpas funkcijas lokaliai. Kiekviena funkcija, sukurta su lambda, taip pat gali būti sukurta su def. Tačiau atvirkščiai tai nėra tiesa.
Sintaksės lygiu lambda ir def yra raktiniai žodžiai. Vienas pagrindinis skirtumas tarp jų yra Python griežtas teiginių ir išraiškų atskyrimas. Teiginiai yra kodo vykdymo žingsniai, o išraiškos yra įvertinamos kaip vertė.
Def pradeda teiginį, tiksliau sudėtinį teiginį, kuris apima kitus teiginius. def teiginyje gali būti tik return teiginiai. return teiginys grąžina reikšmę, kai iškviečiama funkcija, apibrėžta def.
Skirtingai nei def teiginys, lambda pradeda išraišką, kurioje negali būti jokių teiginių. Lambda išraiška priima vieną ar daugiau argumentų ir grąžina anoniminę funkciją. Kai lambda funkcija yra iškviečiama, joje esanti išraiška yra įvertinama su perduotais argumentais ir grąžinama.
Kokie yra Python lambda išraiškų apribojimai?
Python sąmoningai apribojo lambda funkcijų naudingumą, nes paprastai geriau yra pavadinti funkcijas. Tai verčia programuotojus galvoti apie funkcijos reikšmę ir aiškiai atskirti jos dalis.
Lambda funkcijos negali turėti instrukcijų, skirtingai nei funkcijos, apibrėžtos raktiniu žodžiu def, kūnas. Todėl lambda funkcijoje negalima naudoti if, for ir pan. Taip pat negalima sukelti išimties, nes tam reikalingas raise teiginys.
Python kalbos lambda funkcijos gali turėti vieną išraišką, kuri įvertinama ją iškvietus. Lambda išraiškoje negalima naudoti tipo anotacijų. Šiandien dauguma Python kalbos lambda funkcijų naudojimo atvejų naudoja kitas technikas, pavyzdžiui, supratimus.
Įvairūs lambda funkcijų naudojimo būdai Python kalboje
Lambda išvestos iš funkcinio programavimo. Kai kuriose kalbose, pavyzdžiui, JavaScript, anoniminės funkcijos plačiai naudojamos be specialaus raktažodžio. Python kalboje lambda išraiškos naudojamos nedidelėms funkcijoms kurti lokaliai. Toliau apžvelgsime jų naudingiausius pritaikymus.
Kaip užpildyti aukštesnės eilės funkcijas Python kalboje naudojant lambda išraiškas
Lambdos dažnai naudojamos su aukštesnės eilės funkcijomis, pvz., map(), filter() ir reduce(). Dėl lambdų iteruojamo elemento elementai gali būti transformuojami be ciklų. Aukštesnės eilės funkcijos yra funkcijos, kurios kaip parametrus naudoja funkcijas arba grąžina funkciją.
Funkcija map() priima funkciją ir iteruojamąjį kaip parametrus. Ji vykdo funkciją kiekvienam iteruojamojo elementui. Pabandykime sugeneruoti kvadratinius skaičius. Naudojame funkciją map() ir perduodame lambda išraišką kaip argumentą, kuris sugeneruoja kvadratinę funkciją. Kvadratinė funkcija taikoma kiekvienam sąrašo elementui su 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]pythonNuo Python 3.0 versijos map() ir filter() funkcijos grąžina iteruojamą objektą, o ne sąrašą. list() iškvietimas naudojamas assert teiginiuose, kad išpakuotų iteruojamus objektus į sąrašą.
Sąrašų supratimas siūlo modernesnį požiūrį į iteruojamų elementų apdorojimą. Vietoj to, kad naudotume map() ir generuotume lambda funkciją, galime tiesiogiai apibūdinti operaciją:
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]pythonFunkcija filter() gali būti naudojama iteruojamo elemento elementams filtruoti. Mes galime išplėsti mūsų pavyzdį, kad būtų generuojami tik lyginiai kvadratiniai skaičiai:
# 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]pythonPateikiame pageidaujamą metodą, kai naudojamas sąrašo supratimas, kad būtų gautas tas pats rezultatas nenaudojant lambda ir aukštesnės eilės funkcijų. if supratimo dalis naudojama, kad būtų atrinkti lyginiai skaičiai iš generuotų kvadratinių skaičių:
# 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 nuo Python 3.0 versijos nėra įtraukta į standartinę biblioteką. Ši funkcija yra functools modulyje.
Kaip įgyvendinti pagrindines funkcijas Python kalboje naudojant lambda funkcijas
Supratimas iš esmės pakeitė klasikinės aukštesnės eilės funkcijas map() ir filter() Python kalboje. Tačiau pagrindinės funkcijos gali būti naudojamos norint parodyti visus lambda funkcijų privalumus.
Python palyginimo funkcijos sorted(), min() ir max() veikia iteruojamuose objektuose. Kiekvienas iteruojamo objekto elementas yra palyginamas, kai funkcija yra iškviečiama. Šios trys funkcijos priima raktinę funkciją kaip neprivalomą parametrą key. Raktinė funkcija yra iškviečiama kiekvienam elementui ir grąžina raktinę vertę palyginimo operacijai.
Apsvarstykime šią problemą. Turime aplanką su vaizdo failais, kurių pavadinimai yra susieti su Python sąrašu. Norime surūšiuoti sąrašą. Visi failų pavadinimai prasideda skaičiumi img, po kurio eina kitas skaičius:
# List of image file names
images = ['img1', 'img2', 'img30', 'img3', 'img22', 'img100']pythonJei naudojame Python sorted() funkciją, taikoma leksikografinė tvarka. Ji traktuoja iš eilės einančius skaitmenis kaip vieną skaičių. Taigi skaičiai ['1', '2', '100'] yra išdėstomi tvarka ['1', '100', '2']. Rezultatas nėra toks, kokio tikimės:
# Sort using lexicographic order
sorted_image = sorted(images)
# Show that it works
assert sorted_image == ['img1', 'img100', 'img2', 'img22', 'img3', 'img30']pythonMes perduodame lambda išraišką, kuri sukuria raktinę funkciją, kad užtikrintume teisingą rūšiavimą. Raktinė funkcija išskiria failo vardo skaitmeninę dalį, kuri naudojama kaip raktas sorted():
# 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']pythonPagrindinė funkcija naudojama lokaliai ir tik vieną kartą. Nėra būtina apibrėžti papildomos pavadintos funkcijos. Lambdos yra teisingas būdas kurti pagrindines funkcijas. Pažvelkime į dar du pavyzdžius.
Kaip ir sorted(), įdiegtos Python funkcijos min() ir max() naudoja pasirinktinę raktų funkciją. Šios funkcijos suranda mažiausią ir didžiausią elementą sąraše ar kitame kartotiniame objekte. Mažiausias ar didžiausias elementas yra apibrėžimo klausimas ir gali būti nurodytas naudojant raktų funkciją.
Aišku, ką reiškia mažiausias arba didžiausias elementas paprastų verčių sąrašuose, pavyzdžiui, skaičių sąraše. Šiuo atveju specialios raktinės funkcijos nereikia:
nums = [42, 69, 51, 13]
assert min(nums) == 13
assert max(nums) == 69pythonJei raktinė funkcija neperduodama, kaip numatytoji naudojama tapatybės funkcija f(x) = x. Tai galima lengvai apibrėžti kaip Python lambda su lambda x: x.
Bet kas, jei kiekvienas iteruojamo elemento elementas apima kelias datas? Įsivaizduokime sąrašą, kuriame yra žmonių vardai ir amžius. Kokie yra kriterijai, pagal kuriuos sprendžiama, kuris iš min() ir max() yra mažiausias ir didžiausias elementas? Čia praverčia raktinė funkcija.
Mums reikia pavyzdinių duomenų, kad galėtume iliustruoti, kaip veikia pagrindinės funkcijos. Sukurkime funkciją Person(), kuri veiks kaip konstruktorius:
# 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}pythonMes sukuriame žmonių sąrašą naudodami mūsų konstruktoriaus funkciją:
# Create list of people
people = [person('Jim', 42), person('Jack', 51), person('John', 69)]pythonRasti vyriausią asmenį naudojant max() skambutį. Tai sukuria raktinę funkciją naudojant lambda išraišką, kuri paima asmens žodyną ir iš jo išskiria amžių kaip palyginimo elementą:
# Find the oldest person
oldest = max(people, key=lambda person: person['age'])
# Check that it works
assert oldest == Person('John', 69)pythonŠis metodas veikia lygiai taip pat ir min() funkcijai. Šiuo atveju apibrėšime pagrindinę funkciją už min() iškvietimo ribų ir vėl panaudosime lambda išraišką. Tai pagerina skaitomumą ir yra naudinga, jei pagrindinė funkcija turi kelis vietinius naudojimus:
# 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)pythonKaip sukurti uždarymus naudojant Python lambda funkcijas
Python lambda taip pat naudojamos apibrėžiant uždarymus. Tai yra funkcijos, kurias sukuria kitos funkcijos ir kurios saugo vertę. Uždarymai gali būti naudojami panašių funkcijų šeimoms kurti. Pateiksime dažną pavyzdį, kai kuriamos galios funkcijos.
Eksponentinės funkcijos priima argumentą ir pakelia jį laipsniu. Gerai žinomi pavyzdžiai yra kvadratinė funkcija f(x) = x ^ 2 ir kubinė funkcija f(x) = x ^ 3. Bet kokios eksponentinės funkcijos gali būti generuojamos kaip uždarymai naudojant konstruktoriaus funkciją. Naudosime lambda išraišką, o tai reiškia, kad mums nereikės apibrėžti vidinės pavadintos funkcijos:
# 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) == 1000pythonKaip naudoti iškart iškviečiamą funkcijos išraišką (IIFE) su Python lambda funkcijomis
IIFE, tariama „iffy“, yra žinomas JavaScript modelis. Jis apima anoniminės funkcijos apibrėžimą ir jos nedelsiamą vykdymą.
Lambdas gali būti naudojamos kaip IIFE, nors dėl Python apribojimų jos nėra labai naudingos. Mums reikia tik įdėti skliaustelius aplink lambda išraišką:
(lambda num: num * num)pythonIr dar viena pora skliaustų, kuriuose yra argumentas (-ai):
assert (lambda num: num * num)(3) == 9python