Vadovėlis/Pažangios funkcijos

Iš Pitonas.


Pažangesnės funkcijos

Papasakosiu tau apie keletą neįtikėtinų funkcijų ir gudrybių, kurios padės supaprastinti užduočių atlikimą. Pradėkime :)

Lambda funkcija

Jau žinai kaip apsirašyti funkciją su žodeliu ‘’def’’. Lambda funkcija yra tokia pati funkcija, tik labai trumpa ir anoniminė - ji neturi jokio vardo. Kai reikia apibrėžti labai trumpą ir paprastą funkciją, kurią naudosime tik vieną kartą ir kuri nereikalauja sudėtingos logikos, galime naudoti lambda funkciją. Tai gali būti ypač naudinga, kai turime sudėtingą funkciją, kurią norime išskaidyti į smulkesnes dalis, arba kai norime panaudoti funkciją kaip argumentą kitai funkcijai. Lambda funkcijos sintaksė yra paprasta, rašome žodį lambda, po to tarp skliaustų nurodome argumentų sąrašą ir funkcijos išraišką. Tai viskas, ko mums reikia, kad apibrėžtume lambda funkciją.

Lambda funkcijos yra naudojamos daugeliui Python standartinių funkcijų, pavyzdžiui, filter(), map(), sorted(), kad būtų paprastesnis kodas. Apie jas daugiau papasakosiu šiame skyriuje, o dabar pažiūrėkime, kaip galime panaudoti lambda funkciją:

# lambda funkcija apskaičiuojanti kvadratą
kvadratas = lambda x: x**2

print(kvadratas(5)) # 25

# lambda funkcija filtruojanti nelyginius skaičius
skaičiai = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
nelyginiai = list(filter(lambda x: x % 2 != 0, skaičiai))

print(nelyginiai) # [1, 3, 5, 7, 9]

Lambda funkcija taip pat gali būti naudinga, kai reikia perduoti funkciją kaip argumentą į kitą funkciją. Tai leidžia sukurti trumpą, paprastą ir lengvai suprantamą kodą.

Rikiavimas su sorted()

Anksčiau rodžiau rikiavimo funkciją su sąrašais. Sąrašo funkcija sąrašas.sort() modifikuoja savo elementus juos surikiuodamas. Taip kintamasis pakeičia savo reikšmę. Python taip pat turi funkciją sorted() kuri grąžina naują surikiuotą rezultatą, nepakeisdama originalaus kintamojo. Pažiūrėkim, kaip tai veikia:

# susikuriame sąrašą su atsitiktiniais skaičiais
sąrašas = [3,1,5,23,0]
# sorted grąžina surikiuotą sąrašą, kuri priskiriame naujajam kintamajam.
surikiuotas_sąrašas = sorted(sąrašas)

# atsispausdiname rezultatą. Matysi, kad kintamasis sąrašas nepakeitė reikšmės, o surikiuotas_sąrašas reikšmė yra surikiuota.
print(surikiuotas_sąrašas, sąrašas)

# pažiūrėkim, ką padarys funkcija sort()
sąrašas.sort()
# rezultate matysi du surikiuotus identiškus sąrašus.
print(surikiuotas_sąrašas, sąrašas)

# kaip surikiuoti mažėjančia tvarka? Tiesiog pridėkime prie funkcijos reverse=True
atbulas_sąrašas = sorted(surikiuotas_sąrašas, reverse=True)
print(atbulas_sąrašas, surikiuotas_sąrašas, sąrašas)

Rezultatus turėtum matyti tokius:

[0, 1, 3, 5, 23] [3, 1, 5, 23, 0]
[0, 1, 3, 5, 23] [0, 1, 3, 5, 23]
[23, 5, 3, 1, 0] [0, 1, 3, 5, 23] [0, 1, 3, 5, 23]

Akylus skaitytojas pamatys, kad pavyzdyje parodžiau papildomą sorted funkcionalumą atbuliniam sąrašo rikiavimui: sorted(sąrašas, reverse=True). reverse anglų kalboje reiškia atbulinis, todėl tai pasako funkcijai, kad mums reikia grąžint sąrašą atbuline tvarka.

Dar vienas labai svarbus skirtumas tarp sąrašas.sort() ir sorted() - ‘’sorted’’ naudojamas visiems iteruojamiems objektams. Pavyzdžiui anksčiau skyriuje minėtiems žodynams.

# pasirašom funkciją sąrašo atvaizdavimui 
def spausdink(sąrašas):
    for elementas in sąrašas:
        print(elementas)
    print('')

# apsirašom sąrašą žodynų, kuriuos rikiuosime.
žodynai = [
    {"vardas": "Darius", "metai": 15, "pomėgis": "bėgimas"},
    {"vardas": "Marius", "metai": 14, "pomėgis": "krepšinis"},
    {"vardas": "Karolis", "metai": 16, "pomėgis": "krepšinis"},
    {"vardas": "Gileta", "metai": 13, "pomėgis": "tinklinis"},
    {"vardas": "Eglė", "metai": 17, "pomėgis": "bėgimas"},
]

print('surikiuojam pagal metus mažėjančia tvarka')
spausdink(sorted(žodynai, key=lambda x: -x['metai']))

print('rikiuojame pagal dvi reikšmes: pradžioje pagal pomėgį, o vėliau pagal metus didėjančia tvarka.')
spausdink( sorted(žodynai, key=lambda x: (x['pomėgis'], x['metai'])) )
print('nurodome atbuline tvarka')
spausdink( sorted(žodynai, key=lambda x: (x['pomėgis'], x['metai']), reverse=True) )

print('rikiuojame pagal pomėgį didėjančia tvarka, o vėliau pagal metus mažėjančia')
spausdink( sorted(žodynai, key=lambda x: (x['pomėgis'], -x['metai'])) )
print('nurodome atbuline tvarka')
spausdink( sorted(žodynai, key=lambda x: (x['pomėgis'], -x['metai']), reverse=True) )

Rezultatas bus toks:

surikiuojam pagal metus mažėjančia tvarka
{'vardas': 'Eglė', 'metai': 17, 'pomėgis': 'bėgimas'}
{'vardas': 'Karolis', 'metai': 16, 'pomėgis': 'krepšinis'}
{'vardas': 'Darius', 'metai': 15, 'pomėgis': 'bėgimas'}
{'vardas': 'Marius', 'metai': 14, 'pomėgis': 'krepšinis'}
{'vardas': 'Gileta', 'metai': 13, 'pomėgis': 'tinklinis'}

rikiuojame pagal dvi reikšmes: pradžioje pagal pomėgį, o vėliau pagal metus didėjančia tvarka.
{'vardas': 'Darius', 'metai': 15, 'pomėgis': 'bėgimas'}
{'vardas': 'Eglė', 'metai': 17, 'pomėgis': 'bėgimas'}
{'vardas': 'Marius', 'metai': 14, 'pomėgis': 'krepšinis'}
{'vardas': 'Karolis', 'metai': 16, 'pomėgis': 'krepšinis'}
{'vardas': 'Gileta', 'metai': 13, 'pomėgis': 'tinklinis'}

nurodome atbuline tvarka
{'vardas': 'Gileta', 'metai': 13, 'pomėgis': 'tinklinis'}
{'vardas': 'Karolis', 'metai': 16, 'pomėgis': 'krepšinis'}
{'vardas': 'Marius', 'metai': 14, 'pomėgis': 'krepšinis'}
{'vardas': 'Eglė', 'metai': 17, 'pomėgis': 'bėgimas'}
{'vardas': 'Darius', 'metai': 15, 'pomėgis': 'bėgimas'}

rikiuojame pagal pomėgį didėjančia tvarka, o vėliau pagal metus mažėjančia
{'vardas': 'Eglė', 'metai': 17, 'pomėgis': 'bėgimas'}
{'vardas': 'Darius', 'metai': 15, 'pomėgis': 'bėgimas'}
{'vardas': 'Karolis', 'metai': 16, 'pomėgis': 'krepšinis'}
{'vardas': 'Marius', 'metai': 14, 'pomėgis': 'krepšinis'}
{'vardas': 'Gileta', 'metai': 13, 'pomėgis': 'tinklinis'}

nurodome atbuline tvarka
{'vardas': 'Gileta', 'metai': 13, 'pomėgis': 'tinklinis'}
{'vardas': 'Marius', 'metai': 14, 'pomėgis': 'krepšinis'}
{'vardas': 'Karolis', 'metai': 16, 'pomėgis': 'krepšinis'}
{'vardas': 'Darius', 'metai': 15, 'pomėgis': 'bėgimas'}
{'vardas': 'Eglė', 'metai': 17, 'pomėgis': 'bėgimas'}

Norint naudoti funkciją sorted() su žodynais, reikia programai nurodyti, pagal kurią žodyno reikšmę nori rikiuoti sąrašą. Tai gali padaryti nurodydamas key=lambda kintamasis: kintamasis[‘reikšmė’]. Parametras ‘’key’’ nurodo funkcijai ‘’sorted’’, kad norėsi naudoti papildoma funkciją. Štai čia mes paduodame bevardę funkciją ‘’lambda’’, kuri ir nurodo, pagal kuriuos parametrus mes norime rikiuoti sąrašą.

Pagalbininkė map()

map() yra Python vidinė funkcija, kuri leidžia mums taikyti funkciją kiekvienam elementui sąraše ar kitame iteruojamame objekte. Ši funkcija grąžina naują sąrašą, kuriame kiekvienas elementas yra pritaikytas pagal paduotą funkciją.

map(funkcija, sąrašas)
  • ‘’funkcija’’ yra funkcija, kuri bus taikoma kiekvienam elementui sąraše.
  • ‘’sąrašas’’ yra sąrašas, arba kitas iteruojamas objektas.

Pažiūrėkime į pavyzdį:

# sukuriame sąrašą skaičių
skaičiai = [1, 2, 3, 4, 5]

# apibrėžiame funkciją, kurią norime pritaikyti kiekvienam elementui
def kvadratas(x):
    return x**2

# naudojame map() funkciją, kad pritaikytume funkciją kiekvienam sąrašo elementui
skaičiai_kvadratu = map(kvadratas, skaičiai)

# išspausdiname naują sąrašą, kuriame kiekvienas skaičius yra pakeltas kvadratu
print(list(skaičiai_kvadratu)) # [1, 4, 9, 16, 25]

Taip pat galime naudoti lambda funkcijas, kad nurodytume funkciją tiesiogiai map() funkcijos viduje, kaip gali pamatyti čia:

# sukuriame sąrašą skaičių
skaičiai = [1, 2, 3, 4, 5]

# naudojame lambda funkciją, kad apibrėžtume funkciją tiesiogiai map() viduje
skaičiai_kvadratu = map(lambda x: x**2, skaičiai)

# išspausdiname naują sąrašą, kuriame kiekvienas skaičius yra pakeltas kvadratu
print(list(skaičiai_kvadratu)) # [1, 4, 9, 16, 25]

map() funkcija yra naudinga, kai reikia greitai ir efektyviai pritaikyti tam tikrą funkciją kiekvienam sąrašo ar kitame iteruojamame objekte esančiam elementui, ir gauti naują sąrašą su apdorotais elementais.

Beje, ar atkreipei dėmesį, kad norint atspausdinti sąrašą, aš panaudojau funkciją list(). Ar žinai kodėl?

Tai yra dėl to, kad map() funkcija grąžina iteruojamą objektą, kuris yra vadinamas generatoriumi. Generatorius yra specialus iteruojamas objektas, kuris leidžia gauti reikiamus duomenis vieną po kito pagal poreikį, taip sutaupant atminties resursus. Tačiau, norint matyti visus elementus iš karto, reikia sukurti sąrašą ar kitą tipo objektą, kuris saugotų visus map() funkcijos grąžinamus elementus. Tai padaryti galime, panaudoję list() funkciją, kuri konvertuoja generatoriaus grąžinamą objektą į sąrašą.

Filtravimas su filter()

filter() yra Python funkcija, kuri leidžia filtruoti duomenis pagal tam tikras sąlygas. Ši funkcija veikia pagal panašų principą kaip map() funkcija, tačiau jos veikimo būdas yra kitoks. filter() funkcija taiko nurodytą sąlygą (funkciją) kiekvienam elementui iteruojamame objekte ir grąžina tik tuos elementus, kuriuos ta sąlyga tenkina. Tai yra, funkcija išfiltruoja tik tuos elementus, kurie tenkina nurodytą sąlygą.

filter() funkcija naudojama kartu su lambda funkcijomis arba kitomis funkcijomis, kurios grąžina True arba False. Kai reikia išgauti tik tuos elementus, kurie tenkina nurodytą sąlygą, naudojama filter() funkcija.

Pavyzdžiui, norint išfiltruoti tik lyginius skaičius iš sąrašo, galime naudoti šią filter() funkcijos ir lambda funkcijos kombinaciją:

# Sukuriamas sąrašas skaičių
skaičiai = [1, 2, 3, 4, 5]

# Sukuriamas naujas sąrašas tik su lyginiais skaičiais naudojant filter() ir lambda funkciją
lyginiai_skaičiai = filter(lambda x: x % 2 == 0, skaičiai)

# Išspausdinamas naujas sąrašas tik su lyginiais skaičiais
print(list(lyginiai_skaičiai)) # [2, 4]

Šioje situacijoje, filter() funkcija išfiltruoja tik tuos skaičius, kurių liekana yra lygi nuliui (t.y. tik lyginiai skaičiai).