PYTHON liburua/Kontrol-egiturak

Wikibookstik

4. Kontrol-egiturak[aldatu]

Kontrol-egituren bidez programako agindu bat baldintza baten arabera exekutatzeko edo ez, edo agindu batzuen exekuzioa hainbatetan errepikatzeko aukera dago. Aurreko kapituluan azterturiko programak guztiz linealak eta sekuentzialak dira; bakarrik balio dute formulak kalkulatzeko, espresioak kalkulatzeko. Baina programako aginduen exekuzioa modu ez-linealean ere egin daiteke, horretarako balio dute kontrol-egiturek. Programako aldagaien balioen arabera zenbait agindu exekutatu ala ez kontrola dezakegu baldintzazko egiturak erabiliz, edota agindu multzo baten egikaritzapena hainbatetan errepika dadin kontrola dezakegu egitura errepikakorrak erabiliz. Programetako aginduen exekuzioa kontrolatzeko egitura horiek Python lengoaiaz nola idatzi eta erabiltzen diren azaltzea da kapitulu honen helburua.

Baldintzapeko egituren aldetik if kontrol-egitura da ohikoena. Espresio logiko baten balioaren arabera agindu bat edo beste agindu alternatibo bat exekutatuko da. Agindu bat edo agindu-multzo bat hainbat alditan errepikatzea nahi bada, egitura errepikakorrak erabiliko dira. Errepikapenen kopurua hasieran jakina den kasuan edo ez-jakina denean, kontrol-egitura desberdinak erabiliko dira. Jakina bada, errepikapenen kopurua zenbatuko duen kontrol-aldagai bat erabiliko da, soilik errepikapen horiek egikari daitezen. Ez-jakina bada, baldintza baten menpe egotea edo begizta infinitua izatea gerta daiteke. Horrelakoetan, while kontrol-egitura da erabili ohi den egitura errepikakorra, aurrekorako, berriz, while edo for egiturak.

Kontrol-egitura oso bat (if, for edo while erakoak) agindu moduan erabil daiteke programetan. 2. kapituluan esan genuen programa bat agindu-segida ordenatu bat dela, eta programa sinpleenetan hiru moduko aginduak baino ez zeudela:

  • datuak irakurtzeko input modukoak
  • esleipenak (kalkuluak egiteko eta aldagaietan gordetzeko)
  • emaitzak inprimatzeko print modukoak

Kontrol-egiturak ere beste aginduak (sententziak) dira. Kapitulu honetan kontrol egitura horiek guztiak deskribatuko dira, eta egitura horiekin egindako programak azalduko dira, ezaugarriak ezagutzeaz gain egitura horiei dagozkien aplikazioak ere erakusteko asmoz. Azkenik, kasu arraro batzuetan egitura errepikakorren baldintza sinplifikatzearren badaude bi agindu berezi errepikatze-kontrolean eragiteko: continue eta break. Horien erabilera ere azalduko da.

4.1. IF KONTROL-EGITURA[aldatu]

if egiturak balio du agindu-multzo bat soilik kasu batzuetan egikaritzeko, baldintza bat betetzen denean, alegia. Kontrol-egitura hau programazio-lengoaia guztietan dago. Hala ere, Python lengoaian erabiltzen denean, idazkeran (sintaxian) bi diferentzia azpimarratu behar dira:

  • Baldintza ondoren ':' karakterea idatzi behar da, bai eta else hitz erreserbatuaren ondoren ere.
  • Esan den bezala, tabulazioaren erabilera oso zurruna da Pythonen, programako blokeen egitura ondo islatu behar da tabulazioaren bitartez. Agindu-bloke berri bat tabulazio batez bereizten da, eta blokeko agindu guztiak lerrokatuta azaldu behar dira tabulazio-maila berdinarekin.

Egituraren eredua hau da:

if baldintza: 
   aginduak 
else:  
   aginduak

Baldintza espresio boolear baten bidez (ikus aurreko kapitulua) adierazten da. Baldintza betetzen bada, segidan duen agindu-multzoa egikarituko da. Baldintza bete ezean, *else* adarra baldin badago adar horri dagokion agindu-multzoa egikarituko da. Ez badago *else* adarra, berriz, egitura honetan ez da ezer egingo.

Hautazkoa da else adarra idaztea. Adibidez, ondoko programa-zatian agertzen den *if* egitura sinplea da:

if n < 0:  
  n = -n; # Balio absolutua

Aldiz, honako zati honetan egitura osoa dugu:

# Zenbaki positiboen balioaren erdia  
if n < 0:  
   print ("Errorea: negatiboa")  
else:  
   em = n/2  
   print (em)

4.1. programan adibide oso bat dugu, bi zenbakiren artean handiena kalkulatzen duena.

4.1. programa. Baldintzazko egituraren adibidea, bi balioren artean handiena kalkulatzen duena:

# zenbaki handiena kalkulatzeko
a = int(input("sakatu bi zenbakietako bat: "))
b = int(input("sakatu bestea: "))
if a > b:
	hand=a
else:
	hand=b
print("handiena:", hand)

Ondoko ñabardura hauek hartu behar dira kontuan:

  • Baldintzazko espresioan berdintasuna adierazteko == eragilea erabili behar da eta ez = eragilea (esleipenetan bakarrik erabiltzen da hori).
  • != eragilea erabiltzen da balio desberdinak bereizteko.
  • Baldintzazko espresioa and, or eta not eragileekin osaturiko baldintza konposatua izan daiteke.
  • Eragilerik erabiltzen ez bada, alegia, aldagai baten izena besterik erabiltzen ez bada if egituraren baldintza gisa, emaitza egiazkoa izango da aldagaiaren balioa None edo hutsa (string hutsa, zerrenda hutsa, 0 zenbakia... ) ez den bitartean.
  • if egitura baten barruan beste if egitura bat egon daiteke, horrelakoetan if habiaratua esaten diogu bigarrenari. Horren ondoren else bat aurkitutakoan, lehenengoari edo bigarrenari ote dagokion zalantza egon daiteke. Horrelakoetan tabulazioa da agintzen duena. Adibidez:

4.2. programa. Bi aukera daude *if* egitura habiaratuan else adarra kokatzeko.

# if habiatuak
x = int(input("sakatu x: ")) 
y = int(input("sakatu y: ")) 
# else bigarren if-ari dagokionean
if x == 1:
	if y == 2:
		print("12")
	else:
		print("1x")
print(x,y)
# else lehen if-ari dagokionean
if x == 1:
	if y == 2:
		print("12")
else:
	print("x")

Gainera, elif ere erabili daiteke else adarraren ordez "else if" adierazteko. Horrela, ondoko kodean if baten barruan hiru adar agertzen dira:

if n < 0: 
   print ("negatiboa") 
elif n==0: 
   print ("zero") 
else: 
   print ("positiboa")

Baliokidea den beste honen idazketa sinplifikatua da:

if n < 0: 
   print ("negatiboa") 
else: 
   if n==0: 
   print ("zero") 
   else: 
      print ("positiboa")

Baldintza konposatuak adieraz daitezke not, and eta or eragileen bitartez. Adibidez, 4.2. programaren lehen bi sententziak (bi if) bakar batez ordezka litezke (baita programaren bigarren agerpenean ere):

if (x == 1) and (y == 2):

4.2. WHILE KONTROL-EGITURA[aldatu]

Egitura errepikakor orokorrena da while. Prototipoa ondokoa da:

while jarraitzeko-baldintza:    
   aginduak


Jarraitzeko baldintza —espresio booleartzat hartzen dena— ebaluatu ondoren, egiazkoa (ez None) bada egiturari dagokion sententzia edo sententzia-multzoa exekutatuko da, eta baldintzako espresioa berriro ebaluatzera itzuliko da, begizta osatuz. Espresioaren ebaluazioa faltsua denean, while egitura osoaren exekuzioa bukatutzat emango da eta ondoko sententziara (tabulazioaren arabera) pasatuko da, while egituraren gorputza berriro exekutatu gabe.

Python programen idazkeraren berezitasunak kontrol-egitura honetan ere azltzen dira: tabulazioa zurruna da eta bi puntu karakterea jarri behar da baldintza ondoren. Bi puntuen aurreko espresioa da errepikatzen jarraitzeko baldintza, eta bi puntuen ondoan tabulazio-maila bat barrurago azaltzen diren agindu guztiak behin eta berriro exekutatuko den gorputza (aginduak) da.

Zenbaki baten faktoriala kalkulatzen duen 4.3. programan while egitura bat ikus daiteke. Bertan, egitura errepikakorraren baldintza i<=n da, eta bloke bat osatzen duten bi sententziek osatzen dute gorputza. While egitura errepikakorra if egitura baten barruan dago, else adarrean hain zuzen. Ohartzekoa da tabulazioa nola dagoen eginda: ezker-ezkerrean hasieraketa eta if egitura, koxka bat eskuinerantz sententzia gehienak while egitura barne, eta hirugarren mailan errepikatuko diren bi sententziak. Azken sententzia (print) ez da errepikatuko inolaz ere, 2. mailan dagoelako.

4.3. programa. Zenbaki oso baten faktoriala kalkulatzea while egitura batekin:

# n faktoriala
n=int(input('Sakatu zenbaki bat, faktoriala kalkulatzeko: '))
if n <= 0:
	print ("errorea: zenbaki positiboa behar da")
else:
	fakt = 1
	i = 2
	while i <= n:
		fakt = fakt * i
		i=i+1
	print (fakt)

Sakatu zenbaki bat, faktoriala kalkulatzeko: 7 5040

4.3. FOR .. IN KONTROL-EGITURA[aldatu]

Egitura errepikakor honetan posible da zerrenda eta datu-egitura batzuetan elementu bakoitzerako agindu batzuk errepikatzea. Egitura horiei iteragarri (iterable) esaten zaie. Kontuan hartu behar da beste lengoaietako bektoreak eta matrizeak ere zerrendak direla (hurrengo kapituluetan azalduko da). Prototipoa ondokoa da:

for aldagaia in zerrenda: 
   aginduak # aldagaia erabiliko da elementua aipatzeko

C bezalako lengoaietan ez dagoen egitura hau oso erosoa da aurreko kapituluan aipatutako egitura konplexuetan: zerrendak eta hiztegiak.

Adibide gisa, 4.4. programak zerrenda bateko elementu guztiak tratatzen ditu.

4.4. programa. Zerrenda bateko elementu guztiak idaztea *for .. in* kontrol-egitura batekin.

zerrenda = ['negatiboa','zero','positiboa']
for elem in zerrenda:
	print ("Osagaia:", elem)


Programa horren exekuzioak honako irteera hau sortuko luke:

>>> 
Osagaia: negatiboa 
Osagaia: zero 
Osagaia: positiboa


Beste lengoaia batzuetan ohikoa da for kontrol-egitura kopuru batez gobernatzea. C lengoaiaz, adibidez, for(i=1;i<n;i++) moduko egitura oso ohikoa da. Pythonez hori egiteko range erabiltzea da irtenbide zuzenena. Zerrenda baten osagai guztiei edo string baten karaktere guztiei dagokien iterazioa kontrolatzeko range funtzioa erabili ohi da. Osagai kopurua, zenbaki bat alegia, da range funtzioaren parametroa, emaitza 0 eta balio horren arteko osoko balio guztiak izanik. for in range() ohiko egitura bihurtuko zaigu. 4.5. programan adibide bat dugu.

4.5. programa. string baten karaktereak kontatzea range funtzioa erabiliz:

katea=input('Sakatu karaktere-katea: ') 
kar=input('Sakatu kontatzeko karakterea: ') 
luzera=len(katea) 
kont = 0
for i in range(luzera): 
	if katea[i] == kar: 
		kont = kont+1 
print(kar, ' karakterearen kopurua:', kont)

Eta hau da programa horren exekuzioaren adibide bat:

>>>  
Sakatu karaktere-katea: amama etorri zen atzo 
Sakatu kontatzeko karakterea: a 
a karakterearen kopurua: 4

Edozein kasutan range funtzioan hainbat parametro zehatz daitezke. Adibidean bezala, bakarra bada, balioen heina zero eta zehaztutakoa ken bat izango da. Bi parametroren kasuan, berriz, hasierako balioa eta bukaerakoa zehaztuko dira, bukaerako balio hori heinetik kanpo geratuz. Eta hirugarren parametro batez inkrementatzeko (edo dekrementatzeko) balioa gehi daiteke. Ondoan adibide batzuk, dagokien azalpenarekin:

range(10) # 0-9 tartea 
range(1,13) # 1-12 tartea 
range(2,12,2) # 2 eta 10 arteko zenbaki bikoitiak 
range(10,0,-1) # 10 eta 1 artean ordena beheranzkorrean
ixo

4.4. BREAK ETA CONTINUE AGINDUAK[aldatu]

break sententziak begiztaren bat-bateko amaiera eragiten du, begizta ondoko hurrengo blokera joanez. 4.6. programan "AGUR" (letra larriz) idatzi arte oihartzuna egiten duen programa ikus daiteke.

4.6. programa. Begizta infinitu batean break sententziaren erabilera:

print("Oihartzuna. AGUR sakatu arte ez da ondoko begizta bukatuko");
while True:
	mezu=input("Zure mezua:")
	if (mezu == "AGUR"):
		break;
	print (mezu)
print("AGUR. Bukatu da.")


Egitura errepikakorrak habiratuak egon daitezkeenez, hau da, egitura errepikakor baten blokean beste egitura errepikakor bat egon daitekeenez, break aginduak barrurago dagoen begiztaren amaiera eragiten du. continue sententziak, begiztaren amaiera behartu ordez, uneko iterazioa saihestea eragiten du; hau da, uneko egitura errepikakorreko gorputzean dagoen gainerako aginduak exekutatu gabe berriro jarraitzeko baldintza ebaluatzera doa.

Bien bitartez, jarraitzeko baldintza sinpleagoa izatea lortzen da, salbuespenezko kasuak tratatzeko erabiliz break eta continue. Baina ez da komenigarria break eta continue sententziak erabiltzea, programen irakurgarritasuna zailtzen dute eta, oso salbuespenezko kasuetan bakarrik erabili. 4.6. programa honela ere idatz daiteke modu egokiagoan:

Bertsio txukunagoa
print("Oihartzuna. AGUR sakatu arte ez da ondoko begizta bukatuko"); 
mezu=input("Zure mezua:")
while (mezu != "AGUR"): 
	print (mezu) 
	mezu = input("Zure mezua:") 
print("AGUR. Bukatu da.")

##>>> 
##Oihartzuna. AGUR sakatu arte ez da ondoko begizta bukatuko
##Zure mezua:kaixo
##kaixo
##Zure mezua:kaixo
##kaixo
##Zure mezua:berriro
##berriro
##Zure mezua:AGUR
##AGUR. Bukatu da.

4.5. ADIBIDEAK[aldatu]

4.5.1. 1. enuntziatua: Hirutan handiena[aldatu]

Irakurri hiru zenbaki oso, eta handiena idatzi (soluzioa 4.7. programan).

4.7. programa. if habiratuak 3 zenbakiren arteko handiena kalkulatzeko:

# Hiru zenbakien artean handiena
a = int(input("Sartu lehenengo zenbakia: ")) 
b = int(input("Sartu bigarren zenbakia: ")) 
c = int(input("Sartu azken zenbakia: "))  
if a > b:
	if a > c: 
		print ("Handiena:", a) 
	else: 
		print ("Handiena:", c) 
else: 
	if b > c: 
		print ("Handiena:", b) 
	else: 
		print ("Handiena:", c)

##>>> 
##Sartu lehenengo zenbakia: 23
##Sartu bigarren zenbakia: 7
##Sartu azken zenbakia: 15
##Handiena: 23

4.5.2. 2. enuntziatua: Zerrendakoen batura[aldatu]

Taula baten elementuen batura kalkulatu (hurrengo kapituluetan adibide gehiago daude ohiko datu-egiturak erabiliz) (soluzioa 4.8. programan).

4.8. programa. Taula baten elementuen batura

batura = 0
taula = [2, 4, 6]
for x in taula:
	batura = batura+x 
print ("Batura:", batura)

##>>> 
##Batura: 12

Exekuzioaren adibide bat:

>>>  
Batura: 12

4.5.3. 3. enuntziatua: Atzekoz aurrera[aldatu]

Karaktere-kate bat irakurri teklatutik eta idatzi karaktere horiek atzekoz aurrera (soluzioa 4.9. programan).

4.9. programa. string baten alderantzizkoa:

katea1=input('Tekleatu karaktere-kate bat: ') 
luzera = len(katea1) 
katea2 = "" 
for i in range(luzera): 
	katea2 = katea2 + katea1[luzera-(i+1)] # i 0tik hasten delako  
print('Sarrera:', katea1) 
print('Irteera:', katea2) 

##>>> 
##Tekleatu karaktere-kate bat: Elantxobe
##Sarrera: Elantxobe
##Irteera: eboxtnalE

4.5.4. 4. enuntziatua: Zenbat bateko zenbaki bitarrean[aldatu]

Irakurri zenbaki oso bat eta kalkulatu zero egoeran zenbat bit dagoen karaktere horren ASCII adierazpidean (soluzioa 4.10. programa).

Esan bezala, bit-maneiua oso zaila gertatzen da goi-mailako lengoaietan, baina Pythonen erraza da & (and logikoa), | (or logikoa), ˆ (xor), *<<* (ezker desplazamendua) eta >> (eskuin-desplazamendua) eragileei esker. Adibidean, and eragiketaren bidez bit bat aztertzen da, zeren and eragiketan bit bakar bat 1 egoeran duen maskara batekin datu bat parekatzen dugunean, 1ari dagokion datuaren bita zeroa bada emaitza zero izango baita, eta bata bada, emaitza desberdin zero. Eragiketa 32 aldiz errepikatzen den begizta batean dago (while egituraz), baina bit desberdinak aztertzeko, begiztaren barruan maskarako bitak desplaza daitezke (programan egin den legez), edo datu bera desplazatu.

4.10. programa. Bit-maneiuaren adibidea: zenbaki baten adierazpide bitarraren azterketa:

maskara = 0x00000001
kont = 0
i = 0
datu = int(input("Sakatu zenbaki bat: "))
while i < 32:
	if (datu & maskara)==0:
		kont = kont+1
	maskara = maskara << 1  
	i = i+1
print (datu, "zenbakian:", kont, "bit 0 egoeran") 
print (datu, "zenbakian:", 32-kont, "bit 1 egoeran") 

##>>> 
##Sakatu zenbaki bat: 25
##25 zenbakian: 29 bit 0 egoeran
##25 zenbakian: 3 bit 1 egoeran

25 zenbakia bitarrean hau da: 0000 0000 0000 0000 0000 0000 0001 1001 Hori kontuan hartuta, hau da exekuzioaren adibide bat.

>>>  
Sakatu zenbaki bat: 25 
25 zenbakian: 29 bit 0 egoeran 
25 zenbakian: 3 bit 1 egoeran

4.6. PROPOSATUTAKO ARIKETAK[aldatu]

  1. Osatu 4.7. programa if-else egiturak erabiliz hiru zenbakiak goranzko ordenan idazteko
  2. Aldatu 4.8. programa bigarren taula batean (taula2) zenbaki metatuak lortzeko: lehen osagaia bera izango da, bigarrena lehena eta bigarrenaren batura, 3.a lehen hiruren batura...
  3. 4.9. programan oinarrituta egin programa bat karaktere-kate baten hitzak taula batean sartzeko. Hitzak zuriunez, komaz edo puntuz bereizitako zatiak izango dira. Bukaeran taula osoa inprimatu.
  4. Egin programa bat lehen hogei zenbaki lehenak kalkulatzeko. Egin bigarren bertsio bat 100 baino txikiagoak diren zenbaki lehenak taula batean jartzeko.