Un algoritme és un conjunt de sentències en que alguns blocs s'executen de manera seqüencial, selectiva o repetitiva.

Sentència

Un bloc és un conjunt de sentències que s'executen una després de l'altre.

Connecta't a la màquina virtual python:

> Connect-Wsl python

Comença una nova sessió amb l'interpret de Python:

$ python3
Python 3.12.3 (main, Jul 31 2024, 17:43:48) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Una sentència és el que escrius en l'interpret interactiu de Python abans d'apretar .

A continuació tens l'execució de tres sentències:

>>> x = 45
>>> x += 90
>>> x
135
>>

A continuació tens un graf que representa l'execució de les tres sentències:

flowchart TD
    1["x = 45"] --> 2["x += 90"]
    2 --> 3["x"]

Si vols, enlloc d'utilitzar l'interpret interactiu de Python, pots escriure les sentències en un fitxer i dir a l'interpret de Python que llegeixi el fitxer i que executi les sentències que estan escrites en el fitxer.

Surt de l'interpret interactiur de Python.

Crea el fitxer hello.py amb l'editor nano:

$ nano hello.py

Escriu les tres sentències, una sota de l'altre:

x = 45
x += 90
x

A continuació executa l'interpret de Python amb el fitxer hello.py:

$ python3 hello.py
$

I no passa res 😳.

Si que passa, però no apareix res en pantalla.

A diferència del que passa amb l'interpret interactiu de Python ...

Si vols mostrar coses per pantalla has d'utilitzar la funció print().

Modifica la tercera sentència del fitxer hello.py fer un "print" de la variable x:

x = 45
x += 90
print(x)

Torna a executar el fitxer hello.py:

$ python3 hello.py
135

Ara si que apareix per pantalla el valor de la variable x.

En Python cada linia del fitxer, que no està buida, és una sentència.

Si escrius un programa amb mil linies que no estan buides, tens un programa de mil sentències que s'executen una a continuació de l'altre a no ser que utilitzis una condició o una iteració com veurem més endavant.

Programa

Un exemple de programa senzill és una conjunt d'instruccions que, donat uns valors incials, torna un resultat.

Anem a crear el nostre primer programa que calcula l'àrea d'un cercle.

$ nano circle_area.py

El valor de l'àre d'un cercle es calcula a partir del radi:

radius = 5

PI = 3.141592653
area = PI * (radius ** 2)

print(area)

Si demanem a l'interpret de Python, el fitxer s'executarà de manera seqüencial:

flowchart TD
    1["radius = 5"] --> 2["PI = 3.141592653"]
    2 --> 3["area = PI * (radius ** 2)"]
    3 --> 4["print(area)"]

I el resultat serà l'esperat:

$ python3 circle_area.py 
78.539816325

Ara si volem conèixer l'area d'un cercle de radi 15, podem editar l'scipt circle_area.py i modificar el valor de la variable radius:

radius = 16

PI = 3.141592653
area = PI * (radius ** 2)

print(area)

Podem executar l'script i verificar que funciona:

$ python3 circle_area.py
804.247719168

Però enlloc de tenir que modificar l'script cada cop que hem de calcular un cercle amb radi diferent ...

Si puc imprimir coses per pantalla amb la funció print(), també haig de poder llegir coses per pantalla...

Per això està la funció input():

radius = int(input())

PI = 3.141592653
area = PI * (radius ** 2)

print(area)

Fixa't que hem de covertir l'input en un int amb la funció int().

Si executem l'script sembla aquest es queda aturat esperant l'"input".

$ python3 circle_area.py
16
804.247719168

Has d'escriure el valor del radi i apretar enter.

I aquí tens el teu primer programa!

Només falta que el progama sigui "usable", que l'usuari sàpiga que està passant.

Modifica de nou el fitxer circle_area.py:

radius = int(input("Which radius: "))

PI = 3.141592653
area = PI * (radius ** 2)

print(area)

Ara el programa imprimeix per pantalla l'string "Wich radius: " mentres espera l'"input":

$ python3 circle_area.py
Which radius: 33
3421.194399117

Condició

Una condició és un requisit per procedir amb alguna cosa.

Per exemple, una condició per poder comprar una cosa és que tinguis bastants diners per poder comprar aquesta cosa.

Per exemple, tens 100€ i vols comprar un iPhone de 600€.

Per realitzar la compra has d'utilitzar el programa shop.py:

money = int(input("Euros: "))

print("You have a new iPhone!")

Aquest programa no funciona gaire bé perquè li dones 100€ i et ven un iPhone:

$ python3 shop.py
Euros: 100
You have a new iPhone!

I li dones 0€ i també et dona un iPhone!

$ python3 shop.py
Euros: 0
You have a new iPhone!

El programa ha de verificar que es compleixi una condició: que el diners que li dones siguin igual o superior al preu de l'iPhone!

Per això utilizem l'expresió if <condició> :.

Modifica el codi tal com es mostra a continuació, i molt important, "indenta" el primer print:

money = int(input("Euros: "))

if money > 599 :

    print("You have a new iPhone!")

print("Bye!")

La condició és money > 599.

Si executes el codi de nou pots veure que ara no et venen un iPhone per 100€:

$ pyhton3 shop.py
Euros: 100
Bye!

Però si t'el venen per 600€ o més:

$ python3 shop.py
Euros: 900
You have a new iPhone!
Bye!

El codi funciona, encara que no es gaire informatiu per l'usuari.

Booleà

Una condició és compleix o no es compleix, en el mon de Python no hi ha termes mitjos.

Com que un una condició només pot tenir dos valors sempre es fa servir una expresió de tipus bool (un booleà), alguna cosa que retorna True o False, per executar o no executar un conjut de codi.

Si sumo dos números el resultat és un número:

>>> 100 + 599
699
>>> type (100 + 599)
<class 'int'>

Però si comparo dos números, el resultat és True o False (un valor de la classe bool)

>>> 100 > 599
False
>>> type(100 > 599)
<class 'bool'>
>>> type(False)
<class 'bool'>
>>> False
False

En Python tenim 6 operadors per comparar números:

x == y     # x és igual a y
x != y     # x no és igual a y
x > y      # x és major que y
x < y      # x és menor que y
x >= y     # x és major o igual que y
x <= y     # x és menor o igual que y 

En matemàtiques fem servir = per comparar números o definir equacions, però en Python = es fa servir per assignar valors a les variables.

És un error bastant comú tal com pots provar a continuació:

>>> 3 = 3
  File "<stdin>", line 1
    3 = 3
    ^
SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='?

Python ja et diu que: "Maybe you meant '==' instead of '='?"

Una altre error és enlloc d'escriure >= o <=, escriure => o =<:

>>> 3 => 3
  File "<stdin>", line 1
    3 => 3
    ^
SyntaxError: cannot assign to literal

Execució condicional

A continuació modifiquem el codi:

money = int(input("Euros: "))

iphone = 600

if money >= iphone :

    print("You have a new iPhone!")

print("Bye!")

Pots veure que hem introduit dos millores:

  • Enlloc de comparar directament money amb 600, guardem el valor de l'iphone en la variable iphone i comparem money amb iphone.

  • Utilitzem el comparador >= enlloc de baixar el preu 1€ i comparar amb >.

I per quin motiu no hem escrit directament aquest codi?

Perqué per apendre a programar s'ha d'anar pas a pas, i si et saltes un pas, deixes d'entendre coses i al final et perds.

I ara podem explicar que és l'execució condicional.

Com ja saps de Computació les sentències no poden tenir espais en blanc al principi, a no ser que formin part d'una altre bloc d'execució.

Fina ara només has treballat amb un únic bloc d'execució, el principal, però if afegeix un bloc d'execució condicional.

flowchart TD
    1["money = int(input(#quot;Euros: #quot;))"] --> 2["iphone = 600"]
    2 --> 3["if money >= iphone :"]
    3 --True--> 3_1["print(#quot;You have a new iPhone!#quot;)"]
    3_1 --> 4
    3 --False--> 4["print(#quot;Bye!#quot;)"]

El bloc d'execució condicional s'executa si és cumpleix la condició.

Pyhton sap quines són les sentències que formen part d'aquest bloc perquè estan identades amb el mateix número d'espais en blanc:

A vegades si la condició és True s'ha d'executar un bloc de codi, però si la condició és False també s'ha d'executar un altre bloc de codi.

En aquest casos tenim l'estructura de control if-else.

Per exemple, si money és menor que el que costa l'iPhone podem informar a l'usuari del preu que ha de pagar.

money = int(input("Euros: "))

iphone = 600

if money >= iphone :

    print("You have a new iPhone!")

else:

    print(f"iPhone cost {iphone} euros!")

print("Bye!")

Ara si volem comprar l'iPhone per menys diners del que costa ens avisa de que no pot ser perquè l'iPhone val 600€.

$ python3 shop.py
Euros: 34
iPhone cost 600 euros!
Bye!

Pots veure que ara tenim dos blocs d'execució secundari:

I aquí tens la representació del graf d'execució:

flowchart TD
    1["money = int(input(#quot;Euros: #quot;))"] --> 2["iphone = 600"]
    2 --> 3["if money >= iphone :"]
    3 --True--> 3_1["print(#quot;You have a new iPhone!#quot;)"]
    3_1 --> 5["print(#quot;Bye!#quot;)"]
    3 --False--> 4["else :"]
    4 --> 4_1["print(f#quot;iPhone cost {iphone} euros!#quot;)"]
    4_1 --> 5 

Però el nostre script té el problema que si ens donen més diners del que val l'iPhone no tornem el canvi, i a la llarga això portarà molts poblemes amb els compradors

Un bloc d'execució sencundari és igual que el bloc d'execució primari: també pot tenir if, else, etc.

money = int(input("Euros: "))

iphone = 600

if money >= iphone :

    print("You have a new iPhone!")
    
    if money > iphone :

        print(f"Your change is {money - iphone} euros")
    
    print("Great buy!")

else:

    print(f"The iPhone costs {iphone} euros!")

print("Bye!")

Si ara comprem un iPhone per més de 600 euros, el programa ens torna el canvi:

$ python3 shop.py
Euros: 800
You have a new iPhone!
Your change is 200 euros
Great buy!
Bye!

Els grafs de fluxe estan molt bé per exemple sencills i entendre conceptes.

Però el nostre graf comença a ser una mica complicat de seguir:

flowchart TD
    1["money = int(input(#quot;Euros: #quot;))"] --> 2["iphone = 600"]
    2 --> 3["if money >= iphone :"]
    3 --True--> 3_1["print(#quot;You have a new iPhone!#quot;)"]
    3_1 --> 3_2["if money > iphone :"]
    3_2 --True--> 3_2_1["print(f#quot;Your change is {money - iphone} euros#quot;)"]
    3_2_1 --> 3_3
    3_2 --False--> 3_3["print(#quot;Great buy!#quot;)"]
    3_3 --> 5["print(#quot;Bye!#quot;)"]
    3 --False--> 4["else :"]
    4 --> 4_1["print(f#quot;iPhone cost {iphone} euros!#quot;)"]
    4_1 --> 5 

En canvi, ara que ja comences a saber llegir Python, pots veure que el codi de Python es més fàcil d'entendre que la representació en graf:

Pots veure que hi ha quatre blocs d'execució, un de principal i els altres anidats dins del principal o dins d'un altre.

Això s'anomena programació estructurada:

  • Un programa és una estructura de blocs uns dins dels altres, que s'executen de manera condicional.

  • Cada bloc és un conjunt de sentències que s'executa una després de l'altre.

Operadors lògics

Juntament amb altres operadors, serveixen per a contrastar dues o més condicions.

Per exemple; si volem un número entre 16 i 64; usaràs aquesta condició.

if (n>15) AND (n<65)
   print ("pots treballar")

A diferencia de Java, els operadors lògics s'escriuen amb lletres minúscules (and/or/xor/not)

n = int(input("Introdueix un número enter: "))
if (n>2) and (n<5):
    print ("esta entre 2 y 5")
elif (n>5) or (n<2):
   print("Fora de 2 y 5")
else:
    print("Es un altre cas")

Si executem aquest codi, obtenim:

Introdueix un número enter: -3
Fora de 2 y 5

Si necessites més condicions (la instrucció match) consulta aquest article:

Python switch case statment examples

Tingues en compte que no és habitual l'ús del match, ja que s'ha incorporat força recentment (Python 3.10)

Activitats

1.- Crea un programa que demani a l'usuari el preu de la seva compra.

Si és major a 100 euros s'aplica el 10%, si és major a 50 però menor de 100 un 5% de descompte, en altres casos no té descompte.

Al final del programa has de mostrar el % de descompte i el preu final.

Aquesta solució funciona:

preu_total = float(input("Quin és el preu total de la teva compra (€)? "))

if preu_total >= 100:
    descompte = 10  # 10% de descompte
elif 50 <= preu_total < 100:
    descompte = 5  # 5% de descompte
else:
    descompte = 0   # 0% de descompte

preu_final = preu_total * (1 - descompte / 100)

print(f"Et toca un descompte del {descompte}%. El preu final és de {preu_final:.2f}€.")

Però es pot optar a una solució més senzilla; inicialitzant prèviament el descompte. Sempre heu de vetllar perquè el codi sigui el més senzill possible, ja que així serà més fàcil arreglar-lo (mantenir-lo) si cal.

També podrieu usar el percentatge en número decimal (20% és igual 0.2) però les 2 formes de representar els percentatges són igual de vàlides.

preu_total = float(input("Quin és el preu total de la teva compra (€)? "))
descompte = 0.0

# Condicions per aplicar descompte
if preu_total >= 100:
    descompte = 0.1
elif preu_total >= 50:
    descompte = 0.05

preu_final = preu_total - preu_total * descompte

if preu_final >= 50:
    print(f"Et toca un descompte del {descompte*100}%.")

print(f"El preu final és de {preu_final:.2f}€.")

Provem el codi en els 3 casos:

Quin és el preu total de la teva compra ()? 80
Et toca un descompte del 5.0%. 
El preu final és de 76.00.
Quin és el preu total de la teva compra ()? 100
Et toca un descompte del 10.0%. 
El preu final és de 90.00.
Quin és el preu total de la teva compra ()? 30
El preu final és de 30.00.

Operador condicional ternari.

Com podreu descobrir aviat, als programadors els agraden tota mena de dreceres. Per a les expressions condicionals, també hi ha un truc: podeu escriure una declaració if-else en una línia. Això s'anomena operador ternari i té aquest aspecte:

print("It’s a day now!" if sun else "It’s a night for sure!")

O, de manera més general:

first_alternative if condition else second_alternative

Exemple:

es_bonic = True
estat = "es bonic" if es_bonic else "no es bonic"
print(f"El gat {estat}.")

Resultat:

El gat es bonic.

És una qüestió de comoditat, però recordeu que el codi que creeu encara hauria de ser llegible.

Repetició

En moltes ocasions, ens interessa executar una mateixa sentència moltes vegades. Per evitar repetir-la, que seria molt pesat i propens a errors 🤨, usem les estructures de repetició o bucles.

Bucle while

El bucle while repeteix un bloc de codi sempre que una condició es compleix. És com dir-li a Python: "Repeteix això mentre alguna cosa sigui veritat".

while condició:
    # codi a repetir

Veiem-ho amb un exemple senzill: per exemple, mostrar els números de l'1 al 5.

i = 1
while i <= 5:
    print("El número és:", i)
    i += 1  # Això és el mateix que i = i + 1 o i++
print("Adeu!)

Resultat:

El número és: 1
El número és: 2
El número és: 3
El número és: 4
El número és: 5
Adeu!

A nivell d'esquema, es pot representar de la següent forma:

flowchart TD;
    1["i=1"] --> 2
    2{"while i <=5:"}
    2 --True--> 
    2_1[Print 'El numero és:' i]-->2_2
    2_2["i+=1"] -->2
    2 --False---> 3["Adeu!"]

O, per exemple, mostrar la taula de multiplicar d'un número:

num = 8
i = 1
print(f"Taula del {num}")
while i <= 10:
    print(f"{num} * {i} = {num*i}")
    i += 1 

Resultat:

Taula del 8
8 * 1 = 8
8 * 2 = 16
...
8 * 9 = 72
8 * 10 = 80

Podem usar els bucles per fer un programa que demani a l'usuari números fins que introdueixi un 0. Llavors el programa calcularà i mostrarà la suma de tots els números i acabarà.

suma = 0
numero = None

while numero != 0:
    numero = int(input("Introdueix un número enter (0 per acabar): "))    
    # Afegir el número a la suma si no és 0
    if numero != 0:
        suma += numero

print("La suma total és:", suma)

Resultat.

Introdueix un número (0 per acabar): 12
Introdueix un número (0 per acabar): -4
Introdueix un número (0 per acabar): 10
Introdueix un número (0 per acabar): 0
La suma total és: 18

Com en el cas dels condicionals, separem els blocs de codi per intendacions (per 1 tabulador o 4 espais) i el salt de línia (tecla ENTER) per tancar cada bloc.

Esquema:

Un altre cas habitual on usar bucles és la creació d'una aplicació del terminal que doni la opció de calcular àrea de diversos polígons a l'usuari (1 pel rectangle, 2 pel triangle... ), fins que l'usuari indiqui la opció de sortir de la aplicació.

import math

opcio = -1 

while opcio:
    print("\nOpcions:")
    print("1. Calcular l'àrea d'un quadrat")
    print("2. Calcular l'àrea d'un cercle")
    print("3. Calcular l'àrea d'un triangle")
    print("0. Sortir")

    opcio = int(input("Tria una opció (0-3): "))

    if opcio == 1:
        costat = float(input("Introdueix la longitud del costat del quadrat: "))
        resultat = costat * costat
        print(f"L'àrea del quadrat és: {resultat}")

    elif opcio == 2:
        radi = float(input("Introdueix el radi del cercle: "))
        resultat = math.pi * radi * radi
        print(f"L'àrea del cercle és: {resultat}")

    elif opcio == 3:
        base = float(input("Introdueix la base del triangle: "))
        altura = float(input("Introdueix l'altura del triangle: "))
        resultat = 0.5 * base * altura
        print(f"L'àrea del triangle és: {resultat}")

    elif opcio == 0:
        print("Sortint de l'aplicació. Adéu!")
        break

    else:
        print("Opció no vàlida. Si us plau, tria una opció entre 0 i 3.")

Resultat:

Opcions:
1. Calcular l'àrea d'un quadrat
2. Calcular l'àrea d'un cercle
3. Calcular l'àrea d'un triangle
0. Sortir
Tria una opció (0-3): 1
Introdueix la longitud del costat del quadrat: 2
L'àrea del quadrat és: 4.0

Opcions:
1. Calcular l'àrea d'un quadrat
2. Calcular l'àrea d'un cercle
3. Calcular l'àrea d'un triangle
0. Sortir
Tria una opció (0-3): 0
Sortint de l'aplicació. Adéu!

Bucle for

Per algunes de les operacions repetitives que volem fer és més senzill usar el bucle for.

A Python no existeix el bucle que hi ha a Java:

for (int i=0; i<10; i++)

Però n'hi ha un altre de més potent, que altres llenguatges l'han incorporat més tard (Java, C# ...). És un for que recorre seqüències com string (l'string és una seqüència de caràcters un a un) o bé una llista (la veurem una mica més endavant).

Per exemple, aquest exemple utilitza un bucle for per iterar sobre cada lletra d'una paraula i comptar les aparicions d'una lletra específica.

paraula = input("Introdueix una paraula: ")
lletra_a_comptar = input("Introdueix la lletra que vols comptar: ")

comptador = 0
for lletra in paraula:
    if lletra == lletra_a_comptar:
        comptador += 1

print(f"La lletra '{lletra_a_comptar}' apareix {comptador} vegades a la paraula.")

Resultat:

Introdueix una paraula: Biopython
Introdueix la lletra que vols comptar: o
La lletra 'o' apareix 2 vegades a la paraula.

Activitat.

2.- Crea un programa que mostri per pantalla un triangle d'asteriscs en funció del número que posi l'usuari.

Per exemple, si posa el número 4, el resultat ha de ser:

*
**
***
****

Pista: Recorda que usant una instrucció com aquesta, pots generar n cops un asterisc, depèn del valor de la variable n: print("*" * n). Si n=3 llavors el resultat és ***

num = int(input("Introdueix un número: "))

i = 1

while i <= num:
    print("*" * i)
    i += 1 

3.- Crea un programa que demani a l'usuari una seqüència de nucleòtids (per exemple "ACGTAC") i calculi el número de bases 'G' i 'C' i calculi el percentatge GC.

seq_entrada = input("Introdueix una seqüència de nucleòtids (A, T, C, G): ")

g_count = 0
c_count = 0

for nucleotid in seq_entrada.upper():  # Convertim a majúscules per evitar problemes amb minúscules
    if nucleotid == 'G':
        g_count += 1
    elif nucleotid == 'C':
        c_count += 1

total_nucleotids = len(seq_entrada)

# Calculem el %GC
if total_nucleotids == 0:
    percentatge_gc = 0  # Evitem la divisió per zero si la seqüència és buida
else:
    percentatge_gc = ((g_count + c_count) / total_nucleotids) * 100

print(f"El percentatge de bases GC és: {percentatge_gc:.2f}%")

Script

TODO

#!/bin/python3
...