# Lambda-funktioiden käyttö Pythonissa

Lambda-funktiot ovat olleet **funktionaalisen ohjelmoinnin menetelmä** Python 1.0 **:sta** lähtien. Viime vuosina muut tekniikat ovat kuitenkin saavuttaneet suuremman suosion ja korvanneet lambdat suurelta osin. Siitä huolimatta lambdoilla on edelleen joitakin erikoistuneita käyttötarkoituksia, jotka taitavien Python-ohjelmoijien tulisi tuntea.

## Mitä ovat lambda-funktiot Pythonissa?

Pythonissa **lambda-funktio viittaa nimettömään funktioon**. Python käyttää avainsanaa `lambda` lambda-funktion luomiseen. Lambda-lauseke koostuu avainsanasta `lambda`, jota seuraa argumenttien luettelo, kaksoispiste ja yksittäinen lauseke. Lauseke annetaan argumenteilla ja arvioidaan, kun lambda-funktio kutsutaan:

```none
lambda argument: expression
```

Funktiot ovat lähes jokaisen ohjelmointikielen perusrakenteita, ja ne edustavat pienintä uudelleenkäytettävää koodiyksikköä. Tyypillisesti **Pythonin funktiot määritellään `def`**. Esitämme esimerkkinä neliöfunktion, joka kertoo luvun itsellään:

```python
# Define square function
def square(num):
    return num * num
# Show that it works
assert square(9) == 81
```

`def` on tunnettu tapa määritellä funktioita Pythonissa, mutta kielessä on myös lambda-funktiot. Nämä ovat **nimettömiä funktioita, jotka määrittelevät lausekkeen parametreilla**. Lambda-funktioita voidaan käyttää missä tahansa, missä funktiota odotetaan tai voidaan määrittää nimelle. Voit nähdä neliöfunktiota vastaavan lambda-lausekkeen tässä:

```python
# Create square function
squared = lambda num: num * num
# Show that it works
assert squared(9) == 81
```

Huomio Pythonissa lambda-funktio viittaa funktioon, joka on luotu avainsanalla `lambda`. Lambda ei ole tietyn funktion nimi eikä se ole yksi Python-operaattoreista.

### Mitä eroa on lambda- ja def-sanoilla?

Saattaa tuntua oudolta, että Pythonissa voi luoda funktioita sekä `lambda` että `def`. `Lambda` **ei** kuitenkaan ole **oma ominaisuus**, vaan vain toinen tapa luoda lyhyitä funktioita paikallisesti. Jokainen `lambda` lla luotu funktio voidaan luoda myös `def`. Päinvastoin tämä ei kuitenkaan päde.

Syntaktisella tasolla `lambda` ja `def` ovat molemmat avainsanoja. Yksi keskeinen ero niiden välillä on Pythonin **tiukka lausekkeiden ja lausumien erottelu**. Lausekkeet ovat koodin suorittamisen vaiheita, kun taas lausumat arvioidaan arvoksi.

`Def` aloittaa lauseen, tarkemmin sanottuna yhdistetyn **lauseen, joka sisältää muita lauseita**. `def` voi esiintyä vain `return` lausetta. `return` palauttaa arvon, kun `def` llä määritelty funktio kutsutaan.

Toisin kuin `def`, **`lambda` aloittaa lausekkeen, joka ei voi sisältää lauseita**. Lambda-lauseke ottaa yhden tai useamman argumentin ja palauttaa nimettömän funktion. Kun lambda-funktio kutsutaan, sen sisältämä lauseke arvioidaan annetuilla argumenteilla ja palautetaan.

### Mitkä ovat Pythonin lambda-lausekkeiden rajoitukset?

Python on tarkoituksella rajoittanut lambda-funktioiden käyttökelpoisuutta, koska yleensä on **parempi nimetä funktiot**. Tämä pakottaa ohjelmoijat miettimään funktion merkitystä ja erottamaan osat selkeästi toisistaan.

Lambdat eivät voi sisältää ohjeita, toisin kuin `def` määritellyn funktion runko. Siksi **lambda-funktiossa ei** ole **mahdollista käyttää `if`, `for` jne.** Ei ole myöskään mahdollista laukaista poikkeusta, koska se edellyttää `raise`.

Pythonin lambda-funktiot voivat sisältää yhden lausekkeen, joka arvioidaan kutsuttaessa. **Tyyppimerkintöjä ei voi käyttää** lambda-lausekkeessa. Nykyään useimmissa Pythonin lambda-funktioiden käyttötapauksissa käytetään muita tekniikoita, kuten comprehensions.

## Lambda-funktioiden eri käyttötarkoitukset Pythonissa

Lambdat **ovat peräisin funktionaalisesta ohjelmoinnista**. Joissakin kielissä, kuten JavaScriptissä, nimettömiä funktioita käytetään laajalti ilman erityistä avainsanaa. Pythonissa lambda-lausekkeita käytetään pienten funktioiden luomiseen paikallisesti. Seuraavassa käymme läpi niiden hyödyllisimmät sovellukset.

### Kuinka täyttää korkeamman asteen funktiot Pythonissa lambdoilla

Lambdoja käytetään usein **korkeamman asteen funktioissa, kuten `map()`, `filter()` ja `reduce()`**. Iteroitavan elementit voidaan muuntaa ilman silmukoita lambdojen ansiosta. Korkeamman asteen funktiot ovat funktioita, jotka ottavat parametreiksi funktioita tai palauttavat funktion.

`map()` ottaa parametreina funktion ja iterattavan. Se suorittaa funktion jokaiselle iterattavan elementille. Kokeillaanpa generoida neliölukuja. Käytämme `map()` ja **välitämme argumenttina lambda-lausekkeen**, joka generoi neliöfunktion. Neliöfunktio sovelletaan jokaiselle listan elementille `map()`lla:

```python
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]
```

Huomio Python 3.0:sta alkaen funktiot `map()` ja `filter()` palauttavat iterable-tyyppisen arvon listan sijaan. `list()` kutsu käytetään `assert` -lauseiden sisällä iterable-tyyppisten arvojen purkamiseen listaksi.

List comprehension tarjoaa **modernimman lähestymistavan iterable-tyyppisten tietojen käsittelyyn**. Sen sijaan, että turvautuisimme `map()` een ja luomisimme lambda-funktion, voimme kuvata operaation suoraan:

```python
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]
```

`filter()` voidaan käyttää **suodattamaan iterattavan elementtejä**. Voimme laajentaa esimerkkiämme tuottamaan vain parillisia neliölukuja:

```python
# 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]
```

Esitämme suositellun lähestymistavan, jossa käytetään listan ymmärtämistä **saman tuloksen tuottamiseen ilman lambda-funktioita ja korkeamman asteen funktioita**. Ymmärtämisen osaa `if` käytetään suodattamaan parilliset luvut tuotetuista neliöluvuista:

```python
# 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]
```

Huomio Pythonin `reduce()` -funktiota ei ole sisällytetty vakiokirjastoon Python 3.0:n jälkeen. Tämä funktio löytyy `functools` -moduulista.

### Kuinka toteuttaa keskeisiä toimintoja Pythonissa lambdoilla

Comprehensions ovat suurelta osin korvanneet klassiset korkeamman asteen funktiot `map()` ja `filter()` Pythonissa. Kuitenkin **avainfunktioita voidaan käyttää lambda-funktioiden kaikkien vahvuuksien esittelemiseen**.

Pythonin vertailufunktiot `sorted()`, `min()` ja `max()` toimivat iterable-tyyppisillä kohteilla. Jokainen iterable-tyyppisen kohteen elementti verrataan, kun funktio kutsutaan. Nämä kolme funktiota ottavat vastaan avainfunktion valinnaisena parametrina `key`. Avainfunktio kutsutaan jokaiselle elementille ja palauttaa avainarvon vertailua varten.

Tarkastellaan seuraavaa ongelmaa. Meillä on kansio, jossa on kuvatiedostoja, joiden nimet on liitetty Python-listaan. Haluamme **lajitella luettelon**. Kaikki tiedostonimet alkavat numerolla `img`, jota seuraa numero:

```python
# List of image file names
images = ['img1', 'img2', 'img30', 'img3', 'img22', 'img100']
```

Jos käytämme Pythonin `sorted()`, **käytetään leksikografista järjestystä**. Tämä käsittelee peräkkäisiä numeroita yksittäisinä numeroina. Näin ollen numerot `['1', '2', '100']` sijoitetaan järjestykseen `['1', '100', '2']`. Tulos ei ole odotetun mukainen:

```python
# Sort using lexicographic order
sorted_image = sorted(images)
# Show that it works
assert sorted_image == ['img1', 'img100', 'img2', 'img22', 'img3', 'img30']
```

**Syötämme `lambda`, joka tuottaa avainfunktion**, jolla varmistetaan, että lajittelu on oikea. Avainfunktio poimii tiedostonimen numeerisen osan, jota `sorted()` käyttää avaimena:

```python
# 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']
```

Avainfunktiota käytetään paikallisesti ja vain kerran. Sille ei tarvitse määritellä erillistä nimettyä funktiota. **Lambdat ovat oikea tapa luoda avainfunktioita**. Katsotaanpa vielä kaksi esimerkkiä.

Kuten `sorted()`, myös sisäänrakennetut Python-funktiot `min()` ja `max()` ottavat vastaan valinnaisen avainfunktion. Funktiot etsivät pienimmän ja suurimman elementin listasta tai muusta iterattavasta. **Pienin tai suurin elementti on määritelmäkysymys**, ja se voidaan määrittää avainfunktion avulla.

Yksinkertaisten arvojen luetteloissa, kuten numeroluettelossa, on selvää, mitä pienimmällä tai suurimmalla elementillä tarkoitetaan. Tässä tapauksessa emme tarvitse erityistä avainfunktiota:

```python
nums = [42, 69, 51, 13]
assert min(nums) == 13
assert max(nums) == 69
```

Huomio Jos avainfunktiota ei välitetä, käytetään oletusarvoisesti identiteettifunktiota `f(x) = x`. Tämä voidaan helposti määritellä Python-lambda-funktiona `lambda x: x`.

Mutta entä jos jokainen iterattavan elementti sisältää useita päivämääriä? Kuvitellaan lista sanakirjoista, jotka edustavat ihmisiä heidän nimillään ja ikänsä. Mikä on **kriteeri `min()` lle ja `max()`**, kun päätetään, mikä on pienin ja suurin elementti? Tässä tilanteessa avainfunktio on hyödyllinen.

Tarvitsemme **esimerkkitietoja** havainnollistaaksemme avaintoimintojen toimintaa. Luodaan funktio `Person()`, joka toimii konstruktorina:

```python
# 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}
```

**Luomme luettelon ihmisistä** käyttämällä konstruktorifunktiotamme:

```python
# Create list of people
people = [person('Jim', 42), person('Jack', 51), person('John', 69)]
```

Etsimme vanhimman henkilön käyttämällä `max()`. Tämä **luo avainfunktion** käyttämällä lambda-lauseketta, joka ottaa henkilön sanakirjan ja poimii siitä iän vertailuelementiksi:

```python
# Find the oldest person
oldest = max(people, key=lambda person: person['age'])
# Check that it works
assert oldest == Person('John', 69)
```

Lähestymistapa toimii täsmälleen samalla tavalla `min()` funktiossa. Tässä tapauksessa **määritellään avainfunktio `min()` kutsun ulkopuolella** ja käytetään jälleen lambda-lauseketta. Tämä parantaa luettavuutta ja on hyödyllistä, jos avainfunktiolla on useita paikallisia käyttötarkoituksia:

```python
# 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)
```

### Kuinka luoda sulkeumia Python-lambdoilla

Python-lambdoja käytetään myös sulkeumien määrittelyssä. Nämä ovat funktioita, jotka luodaan muiden funktioiden avulla ja jotka tallentavat arvon. Sulkeumia voidaan **käyttää luomaan** samankaltaisten funktioiden **ryhmiä**. Esitämme yleisen esimerkin, jossa luodaan potenssifunktioita.

Potenssifunktiot ottavat argumentin ja korottavat sen potenssiin. Neliöfunktio `f(x) = x ^ 2` ja kuutiofunktio `f(x) = x ^ 3` ovat tunnettuja esimerkkejä. Mielivaltaisia potenssifunktioita voidaan luoda sulkeumina käyttämällä konstruktorifunktiota. Käytämme lambda-lauseketta, mikä tarkoittaa, että meidän ei tarvitse määritellä sisäistä nimettyä funktiota:

```python
# 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) == 1000
```

### Kuinka käyttää välittömästi kutsuttua funktiolauseketta (IIFE) Python-lambdoilla

IIFE, lausutaan “iffy”, on **tunnettu malli JavaScriptissä**. Siinä määritellään nimetön funktio ja suoritetaan se välittömästi.

**Lambdat voidaan käyttää IIFE-lausekkeina**, vaikka ne eivät ole kovin hyödyllisiä Pythonin rajoitusten vuoksi. Meidän tarvitsee vain laittaa sulkeet lambda-lausekkeen ympärille:

```python
(lambda num: num * num)
```

Ja toinen suluissa oleva argumentti (argumentit):

```python
assert (lambda num: num * num)(3) == 9
```

Vinkki Pythonin aloittelijoille suosittelemme tutustumaan Python-oppaaseemme.


This is a markdown version of: [https://www.ionos.com/fi-fi/digitalguide/verkkosivustot/verkkosivujen-kehittaeminen/lambda-funktiot-pythonissa/](https://www.ionos.com/fi-fi/digitalguide/verkkosivustot/verkkosivujen-kehittaeminen/lambda-funktiot-pythonissa/) for AI/LLM consumption.