> For the complete documentation index, see [llms.txt](https://shsteindorsson.gitbook.io/med-verk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://shsteindorsson.gitbook.io/med-verk/lykkjur-og-skilyrdingar.md).

# Lykkjur og skilyrðingar

## Skilyrðingar

Einn af grundvallarþáttum flestra (og líklega allra) forritunarmála er leið til að *taka ákvarðanir*. Þá er átt við að ákveða hvað skuli gera við ákveðnar aðstæður.

Í þessum hluta kynnumst við algengustu skilyrðingum:

* if
* else
* elif

### if

Fyrsta og einfaldasta skilyrðingin sem við ætlum að skoða er *if-*&#x73;etningin. Hún virkar þannig að hún ber saman tvær segðir (eða fleiri) og ef niðurstaðan er jákvæð, það er að við fáum sannleiksgildið `True`, þá er bálkur setningarinnar (inndregni kóðinn undir henni) inntur (e. executed).

```python
>>> x = 1
>>> y = 2
>>> if x < y:
...     print('X er minna en Y')
...
X er minna en Y
```

Við getum notað eins margar *if-*&#x73;etningar í röð og við viljum og forritið mun sannreyna þær allar.

### else

Þegar við notum *if-*&#x73;etningu höfum við alltaf möguleika á að bæta *else-*&#x73;etningu á eftir (þegar og ef það hentar forritinu).\
Ef skilyrðing *if-*&#x73;etningarinnar á ekki við (er `False`), þá verður bálkur *else-*&#x73;etningarinnar inntur.\
Notkun *else-*&#x73;etninga er valkvæm, það getur einungis ein *else-*&#x73;etning fylgt hverri *if-*&#x73;etningu og það er ekki hægt að nota *else* án þess að *if* komi á undan.

### elif

Lykilorðið `elif` er stytting á *else-if* en þessi setning er gjarnan notuð til að draga úr fjölda *if-*&#x73;etninga. Rétt eins og *else-*&#x73;etningar, þá eru *elif-*&#x73;etningar valkvæmar og eins gildir að ekki er hægt að nota *elif-*&#x73;etningu nema að *if-*&#x73;etning hafi komið á undan (við getum ekki byrjað á *elif*). Ólíkt *else* þá getum við notað *elif* eins oft og við þurfum.

## Lykkjur

Markmið þessa hluta er að kynnast tveimur gerðum lykkja sem eru mikið notaðar, ekki bara í Python heldur í flestum forritunarmálum.\
Í þessum hluta ætlum við að skoða tvær gerðir lykkja:

* **for**
* **while**

#### Hver er munurinn á milli *for* og *while*?

Við gætum skilgreint *for* sem ákveðna lykkju að því leyta að þegar við skrifum *for-*&#x73;etningu þar sem við skilgreinum lykkjuna, þá *ákveðum* við fyrir fram hversu oft hún verður endurtekin.

```python
for <breyta> in <runa>:
    <bálkur lykkjunnar>
```

Í dæminu hér að ofan sjáum við einfalt dæmi um uppbyggingu *for-*&#x6C;ykkju í Python.\
Við skulum byrja á að skoða fyrirbærið `<runa>` en það getur verið hvaða runutag (e. sequence type) sem er til dæmis listi eða tætitafla.\
Ef við höldum áfram að skoða dæmið hér á undan, þá verður `<breyta>` stak úr runutaginu (`<runa>`). Þegar við skrifum *for-*&#x6C;ykkjur getum við notað hvaða breytuheiti sem er en það er hins vegar góð regla að nota lýsandi heiti sem er þó ekki frátekið lykilorð (e. key word) í Python.\
Í síðari línu dæmisins er `<bálkur lykkjunnar>` en það er einfaldlega sá kóði sem lykkjan innir hverju sinni.

Skoðum dæmi þar sem við notum *for-*&#x6C;ykkju til að prenta öll stök listans `nafnalisti`:

```python
>>> nafnalisti = ['Ari', 'Arna', 'Birna', 'Bjarni', 'Blær']
>>> for nafn in nafnalisti:
...     print(nafn)
...
Ari
Arna
Birna
Bjarni
Blær
```

Upp geta komið aðstæður þar sem við viljum einfaldlega að *for-*&#x6C;ykkjan keyri ákveðið oft. Þá getum við notað innbyggt fall sem heitir `range()` (meira um það í kafla um innbyggð föll), en það skilar í raun runu af heiltölum.

Skoðum dæmi um *for-*&#x6C;ykkju þar sem við notum `range()` og inntaksgildið 10:

```python
>>> for tala in range(10):
...     print(tala)
...
0
1
2
3
4
5
6
7
8
9
```

Á móti gætum við kallað *while-*&#x6C;ykkju óákveðna þar sem að hún verður endurtekin svo lengi sem skilyrði hennar eru óbreytt. Ímyndum okkur dæmi þar sem við erum með breytu í forritinu okkar sem við notum sem teljara (köllum hana `teljari`) og við viljum að lykkjan keyri aftur og aftur þar til hann hefur náð ákveðnu marki.\
Skoðum dæmi þar sem við skrifum lykkjusetningu sem skal endurtekin þar til `teljari` hefur náð gildinu 20:

```
while teljari < 20:
    <bálkur lykkjunnar>
```

Það sem við þurfum að hafa í huga varðandi *while-*&#x6C;ykkjur er að ef við notum skilyrði sem nást aldrei, þá hættir hún ekki að keyra. Dæmi um það væri þetta litla forrit:

```python
while True:
    print('Góðan daginn!')
```

Þetta kallast lokuð eða endalaus lykkja og hún hættir ekki án þess að vera stöðvuð handvirkt.

Einn af kostum *while-*&#x6C;ykkjunnar er að við getum skeytt saman skilyrðingum með rökaðgerðum eins og `and`, `or` eða `not` ásamt samanburðarvirkjum (meira um þá í kafla um gagnatög \[Boole]).\
Tökum dæmi þar sem við viljum að lykkjan keyri á meðan breytan `x` hefur gildi yfir 100 en breytan `y` minna en núll:

```python
while x > 100 and y < 0:
    <bálkur lykkjunnar>
```

#### Aðeins meira um *sannleiksgildi*

Í kaflanum um gagnatög er örlítið fjallað um samanburðarvirkja (e. comparison operators). Þar kemur fram að við getum framkvæmt samanburð með samanburðarvirkjum eins og *jafnt-og*, *minna-en*, *ekki-minna-en* (`==`, `<=`, `!=`) og svo framvegis. Niðurstaða þessara samanburða er svo annað hvort `True` eða `False` (*satt* eða *ósatt*).\
Í Python eru nokkur tilfelli sem skila **alltaf** `False`.

| Gildi   | # Athugasemd                                       |
| ------- | -------------------------------------------------- |
| `False` | # False verður `False` (ósatt)                     |
| `[]`    | # Tómur listi (fylki) verður alltaf `False`        |
| `{}`    | # Tóm tætitafla (Python-dictionary) verður `False` |
| `""`    | # Tómur strengur verður `False`                    |
| `0`     | # Heiltalan (int) *Núll* verður `False`            |
| `0.0`   | # Kommutalan *Núll-komma-núll* verður `False`      |
| `None`  | # Tómabendir (e. null pointer) verður `False`      |

Allt annað verður `True` (satt).

Þessar upplýsingar geta komið að gagni við ýmsar aðstæður. Við skulum skoða ímyndað dæmi þar sem við viljum spyrja notanda um nafn og færa undir breytuna `nafn`. Við ætlum að endurtaka kvaðninguna ef notandinn slær ekki inn nafn. Eins og við vitum þá ber tómur strengur sannleiksgildið `False` og við getum nýtt okkur það til að gera kóðann okkar einfaldari:

```python
>>> nafn = ""
>>> while not nafn:
...     nafn = input("Nafn: ")
...
Nafn:
Nafn:
Nafn:
Nafn: Blær
>>> print(nafn)
Blær
```

Við sjáum úr dæminu hér að ofan þá er kvaðningin (`input()`-fallið) endurtekin þar til notandinn slær inn nafn (eða í það minnst streng sem er ekki tómur).\
Setningin `while not nafn:` þýðir því í raun *á meðan* `nafn` *er tómur strengur (*`False`*)*.
