Els programes necessiten emmagatzemar i manipular informació: noms d’usuaris, rutes de fitxers, ports de xarxa, percentatges d’ús, etc. Per fer-ho, usen variables. En aquest article aprendrem què són les variables, quins tipus de dades bàsics ofereix Python i com podem fer-hi feina.
Variables #
Una variable és un nom que associam a un valor emmagatzemat a la memòria de l’ordinador. Podem pensar-hi com una capsa etiquetada: l’etiqueta és el nom de la variable i el contingut és el valor.
Per crear una variable i assignar-li un valor, usam l’operador =:
nom_usuari = "admin"
port_ssh = 22
servei_actiu = TrueA partir d’aquest moment, podem usar el nom de la variable per accedir al seu valor:
>>> nom_usuari = "admin"
>>> print(nom_usuari)
admin
>>> port_ssh = 22
>>> print(port_ssh)
22Les variables poden canviar de valor durant l’execució del programa. Per això es diuen “variables”:
>>> comptador = 1
>>> print(comptador)
1
>>> comptador = 2
>>> print(comptador)
2Noms de variables #
Python té algunes regles sobre quins noms podem usar per a les variables:
- Només poden contenir lletres, números i guions baixos (
_). - No poden començar amb un número.
- No podem usar paraules reservades del llenguatge (
if,for,while,def,class,import,True,False,None, etc.). - Python distingeix entre majúscules i minúscules:
usuari,UsuariiUSUARIsón tres variables diferents.
Exemples de noms vàlids:
nom_usuari = "jaume"
ruta_backup = "/home/backup"
pid_proces = 1234
espai_lliure_gb = 45.5
_variable_interna = "valor"
usuari2 = "maria"Exemples de noms no vàlids:
2usuari = "error" # No pot començar amb un número
nom-usuari = "error" # El guió no està permès, només el guió baix
for = "error" # 'for' és una paraula reservadaConvencions de noms #
A més de les regles obligatòries, hi ha convencions que la comunitat Python segueix per escriure codi llegible. La guia d’estil oficial és el PEP 8 i recomana:
- Usar
snake_caseper a variables i funcions: paraules en minúscules separades per guions baixos. - Usar noms descriptius que expliquin el propòsit de la variable.
Comparem un mal exemple amb un bon exemple:
# Mal exemple: noms curts i poc descriptius
x = "/var/log"
n = 3
a = True
# Bon exemple: noms descriptius
directori_logs = "/var/log"
max_intents = 3
connexio_activa = TrueEl codi amb noms descriptius és més fàcil de llegir i mantenir, especialment quan hi tornam mesos després.
Tipus de dades #
Cada valor a Python té un tipus de dada que determina quines operacions podem fer amb ell. Python té quatre tipus bàsics que usarem constantment:
- Enters (int).
- Decimals (float).
- Cadenes de text (str).
- Booleans (bool).
Enters #
Els nombres enters són nombres sense decimals, tant positius com negatius:
port_ssh = 22
pid_proces = 1547
nombre_usuaris = 150
temperatura = -5Podem fer operacions aritmètiques amb enters:
>>> 10 + 3
13
>>> 10 - 3
7
>>> 10 * 3
30
>>> 10 // 3 # Divisió entera (sense decimals)
3
>>> 10 % 3 # Residu de la divisió (mòdul)
1
>>> 2 ** 10 # Potència (2 elevat a 10)
1024En administració de sistemes, usam enters per a PIDs, ports, nombre de connexions, permisos en octal, etc.
Decimals #
Els nombres decimals, o de coma flotant1, representen valors amb part fraccionària:
espai_total_gb = 500.0
espai_usat_gb = 234.7
percentatge_us = 46.94
temperatura_cpu = 52.5Podem fer les mateixes operacions que amb enters:
>>> 10.0 / 3
3.3333333333333335
>>> 100 * 0.8
80.0Fixem-nos que la divisió amb / sempre retorna un float, mentre que // retorna un enter (divisió entera).
Els nombres decimals tenen una precisió limitada. Per a la majoria de tasques d’administració això no és un problema, però cal tenir-ho en compte si fem càlculs financers o científics.
Cadenes de text #
Les cadenes de text, o strings, representen seqüències de caràcters. Les podem escriure amb cometes simples o dobles:
nom_servidor = "webserver01"
missatge = 'Connexió establerta'
ruta = "/var/log/syslog"Si necessitam incloure cometes dins el text, podem usar l’altre tipus de cometes per delimitar la cadena:
missatge = "L'usuari ha iniciat sessió"
consulta = "SELECT nom, cognom FROM usuari WHERE role = 'admin'"Per a textos multilínia, usam cometes triples:
missatge_error = """Error crític:
El servei no ha pogut iniciar.
Revisau els logs per a més informació."""Booleans #
Els valors booleans només poden ser True (vertader) o False (fals). Són fonamentals per a les decisions dins els programes:
servei_actiu = True
fitxer_existeix = False
connexio_segura = TrueEls booleans solen ser el resultat de comparacions:
>>> 10 > 5
True
>>> 10 < 5
False
>>> "admin" == "admin"
True
>>> "admin" == "root"
FalseEn administració de sistemes, usam booleans per representar estats: un servei està actiu o no, un fitxer existeix o no, una connexió és segura o no.
Inspeccionar el tipus #
Podem usar la funció type() per saber el tipus d’un valor o variable:
>>> type(22)
<class 'int'>
>>> type(3.14)
<class 'float'>
>>> type("hola")
<class 'str'>
>>> type(True)
<class 'bool'>
>>> port = 22
>>> type(port)
<class 'int'>Això és útil quan depuram i volem verificar quin tipus de dada conté una variable.
Tipat dinàmic #
Python és un llenguatge de tipat dinàmic, el que significa que no hem de declarar el tipus d’una variable; Python el dedueix automàticament segons el valor que li assignam. A més, una variable pot canviar de tipus durant l’execució:
>>> valor = 42
>>> type(valor)
<class 'int'>
>>> valor = "ara som text"
>>> type(valor)
<class 'str'>Aquesta flexibilitat és còmoda, però també pot provocar errors si no anam amb compte. És bona pràctica mantenir el mateix tipus per a una variable al llarg del programa.
Operacions amb cadenes #
Les cadenes de text són un dels tipus de dades que més usarem en scripting. Python ofereix moltes operacions per manipular-les.
Concatenació i repetició #
Podem unir cadenes amb l’operador +:
>>> salutacio = "Hola, " + "món!"
>>> print(salutacio)
Hola, món!
>>> nom = "admin"
>>> missatge = "Benvingut, " + nom
>>> print(missatge)
Benvingut, adminI també podem repetir-les amb *:
>>> linia = "-" * 40
>>> print(linia)
----------------------------------------Mètodes i funcions #
La funció len() retorna el nombre de caràcters d’una cadena:
>>> len("administrador")
13
>>> ruta = "/var/log/syslog"
>>> len(ruta)
15Les cadenes tenen molts mètodes incorporats. Els mètodes són funcions que “pertanyen” a un objecte i es criden amb la notació objecte.metode(). Vegem els més útils:
>>> missatge = " Error al servidor "
>>> missatge.strip() # Elimina espais en blanc als extrems
'Error al servidor'
>>> missatge.upper() # Tot en majúscules
' ERROR AL SERVIDOR '
>>> missatge.lower() # Tot en minúscules
' error al servidor '
>>> missatge.replace("Error", "Alerta") # Substituir text
' Alerta al servidor 'Altres mètodes útils:
>>> "webserver01".startswith("web")
True
>>> "webserver01".endswith(".local")
False
>>> "admin:x:1000:1000::/home/admin:/bin/bash".split(":")
['admin', 'x', '1000', '1000', '', '/home/admin', '/bin/bash']
>>> ", ".join(["un", "dos", "tres"])
'un, dos, tres'El mètode split() és especialment útil per processar línies de fitxers de configuració o logs.
Índexs i slicing #
Podem accedir a caràcters individuals usant índexs entre claudàtors. Els índexs comencen a 0:
>>> ruta = "/var/log"
>>> ruta[0]
'/'
>>> ruta[1]
'v'
>>> ruta[-1] # L'últim caràcter
'g'
>>> ruta[-2] # El penúltim
'o'L’slicing ens permet extreure subcadenes amb la sintaxi [inici:fi]:
>>> ruta = "/var/log/syslog"
>>> ruta[0:4] # Des de l'índex 0 fins al 3 (el 4 no s'inclou)
'/var'
>>> ruta[5:8] # Des de l'índex 5 fins al 7
'log'
>>> ruta[9:] # Des de l'índex 9 fins al final
'syslog'
>>> ruta[:4] # Des del principi fins a l'índex 3
'/var'Conversions entre tipus #
Sovint necessitam convertir valors d’un tipus a un altre. Python proporciona funcions per fer-ho:
>>> int("42") # Cadena a enter
42
>>> float("3.14") # Cadena a decimal
3.14
>>> str(22) # Enter a cadena
'22'
>>> str(3.14) # Decimal a cadena
'3.14'
>>> bool(1) # Enter a booleà
True
>>> bool(0)
FalseAquesta operació es coneix com a casting en anglès.
Si intentam convertir un text que no és un nombre vàlid, Python genera un error:
>>> int("hola")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'hola'Més endavant aprendrem a gestionar aquests errors de manera controlada.
Valors falsos #
Quan convertim a booleà, alguns valors es consideren “falsos”:
>>> bool(0)
False
>>> bool(0.0)
False
>>> bool("") # Cadena buida
False
>>> bool([]) # Llista buida
False
>>> bool({}) # Diccionari buid
False
>>> bool(None) # Valor nul
FalseTots els altres valors es consideren “vertaders”. Això és útil perquè podem usar valors directament en condicions sense comparar-los explícitament amb zero o amb cadenes buides.
Formatació de cadenes #
Una de les funcionalitats més útils de Python modern (3.6+) són les f-strings (formatted string literals). Ens permeten inserir valors dins una cadena de manera molt llegible.
La sintaxi és senzilla: posam una f davant les cometes i les variables entre claus {}:
>>> nom = "webserver01"
>>> ip = "192.168.1.100"
>>> port = 443
>>>
>>> missatge = f"Servidor: {nom}, IP: {ip}, Port: {port}"
>>> print(missatge)
Servidor: webserver01, IP: 192.168.1.100, Port: 443Avantatges #
Comparem les dues formes d’aconseguir el mateix resultat:
# Amb concatenació
>>> missatge = "Servidor: " + nom + ", IP: " + ip + ", Port: " + str(port)
# Amb f-string
>>> missatge = f"Servidor: {nom}, IP: {ip}, Port: {port}"Amb f-strings és molt més clar. A més, fixem-nos que amb concatenació hem de convertir port a cadena amb str(), mentre que amb f-strings la conversió és automàtica.
Formatar nombres #
Les f-strings permeten formatar nombres de diverses maneres:
>>> percentatge = 73.456789
>>> print(f"Ús de disc: {percentatge:.2f}%") # Limitar a 2 decimals
Ús de disc: 73.46%
>>> print(f"Valor: {42:5d}") # Forçar 5 caràcters d'ample
Valor: 42
>>> print(f"Codi: {7:03d}") # Omplir amb zeros
Codi: 007Exemples pràctics per a administració:
>>> espai_total = 500
>>> espai_usat = 234.7
>>> percentatge = (espai_usat / espai_total) * 100
>>> print(
... f"Espai usat: {espai_usat:.1f} GB de {espai_total} GB "
... f"({percentatge:.1f}%)"
)
Espai usat: 234.7 GB de 500 GB (46.9%)Expressions #
Podem posar expressions completes dins les claus:
>>> a = 10
>>> b = 3
>>> print(f"La suma de {a} i {b} és {a + b}")
La suma de 10 i 3 es 13
>>> print(f"El resultat de {a} / {b} és {a / b:.2f}")
El resultat de 10 / 3 es 3.33Entrada de dades #
La funció input() ens permet llegir dades que l’usuari escriu per teclat. Accepta un paràmetre opcional que és el missatge que es mostra a l’usuari:
nom = input("Quin és el teu nom? ")
print(f"Hola, {nom}!")
Quin és el teu nom? Jaume
Hola, Jaume!És important recordar que input() sempre retorna una cadena de text, encara que l’usuari escrigui un nombre:
>>> edat = input("Quina edat tens? ")
Quina edat tens? 25
>>> type(edat)
<class 'str'>
>>> edat + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to strPer fer operacions numèriques, hem de convertir el valor:
edat_text = input("Quina edat tens? ")
edat = int(edat_text)
print(f"L'any que ve tendràs {edat + 1} anys.")O de manera més compacta:
edat = int(input("Quina edat tens? "))
print(f"L'any que ve tendràs {edat + 1} anys.")Exemple pràctic #
Un script senzill que demana informació sobre un servidor:
#!/usr/bin/env python3
"""Recull informació bàsica d'un servidor."""
print("=== Informació del servidor ===")
nom = input("Nom del servidor: ")
ip = input("Adreça IP: ")
port = int(input("Port SSH: "))
print()
print(f"Servidor '{nom}' configurat a {ip}:{port}")Constants i convencions #
Python no té constants en el sentit estricte; totes les variables es poden modificar. Tanmateix, per convenció, usam noms en majúscules per indicar que un valor no s’hauria de modificar:
MAX_INTENTS = 3
DIRECTORI_LOGS = "/var/log"
PORT_SSH_DEFECTE = 22
TIMEOUT_SEGONS = 30Quan altres programadors veuen un nom en majúscules, entenen que és un valor constant que no s’ha de canviar durant l’execució del programa.
És habitual definir les constants a la part superior del fitxer, després dels imports:
#!/usr/bin/env python3
"""Script de monitoratge de serveis."""
# Constants
MAX_INTENTS = 3
TIMEOUT_SEGONS = 30
FITXER_LOG = "/var/log/monitoratge.log"
# Codi principal
intents = 0
# ...Exercicis #
Es proposen quatre exercicis pràctics per consolidar els conceptes d’aquest article.
Exercici 1 #
Informació del servidor
Objectiu: Crear variables per emmagatzemar informació d’un servidor i mostrar-les formatades amb f-strings.
- Crea un script anomenat
info_servidor.py. - Defineix variables per a: nom del servidor, adreça IP, port SSH, sistema operatiu i si el servidor està actiu (booleà).
- Mostra tota la informació de manera organitzada usant f-strings.
- Afegeix una línia separadora entre el títol i les dades.
Pista: pots usar la multiplicació de cadenes per crear línies decoratives, e.g.,
"=" * 40.
Resposta
Exemple d’script info_servidor.py:
#!/usr/bin/env python3
"""Mostra informació d'un servidor usant variables i f-strings."""
# Informació del servidor
nom_servidor = "webserver01"
ip = "192.168.1.100"
port_ssh = 22
sistema_operatiu = "Debian 13"
actiu = True
# Mostrar informació
print("=== Informació del servidor ===")
print("=" * 31)
print(f"Nom: {nom_servidor}")
print(f"IP: {ip}")
print(f"Port SSH: {port_ssh}")
print(f"Sistema operatiu: {sistema_operatiu}")
print(f"Actiu: {actiu}")Sortida esperada:
=== Informació del servidor ===
===============================
Nom: webserver01
IP: 192.168.1.100
Port SSH: 22
Sistema operatiu: Debian 13
Actiu: TrueExercici 2 #
Càlcul d’espai en disc
Objectiu: Crear un script que demani a l’usuari informació sobre l’espai en disc i calculi el percentatge d’ús.
- Crea un script anomenat
espai_disc.py. - Demana a l’usuari l’espai total del disc en GB.
- Demana l’espai usat en GB.
- Calcula l’espai lliure i el percentatge d’ús.
- Mostra els resultats amb un decimal de precisió.
Pista: recorda que
input()retorna una cadena i l’hauràs de convertir afloatper fer càlculs.
Resposta
Exemple d’script espai_disc.py:
#!/usr/bin/env python3
"""Calcula l'espai en disc usat i lliure."""
print("=== Càlcul d'espai en disc ===")
# Demanar dades
espai_total = float(input("Espai total del disc (GB): "))
espai_usat = float(input("Espai usat (GB): "))
# Calcular
espai_lliure = espai_total - espai_usat
percentatge_usat = (espai_usat / espai_total) * 100
percentatge_lliure = 100 - percentatge_usat
# Mostrar resultats
print()
print(f"Espai total: {espai_total:.1f} GB")
print(f"Espai usat: {espai_usat:.1f} GB ({percentatge_usat:.1f}%)")
print(f"Espai lliure: {espai_lliure:.1f} GB ({percentatge_lliure:.1f}%)")Exemple d’execució:
=== Càlcul d'espai en disc ===
Espai total del disc (GB): 500
Espai usat (GB): 234.7
Espai total: 500.0 GB
Espai usat: 234.7 GB (46.9%)
Espai lliure: 265.3 GB (53.1%)Exercici 3 #
Processament de rutes
Objectiu: Extreure les parts d’una ruta de fitxer usant mètodes de cadenes i slicing.
- Crea un script anomenat
processa_ruta.py. - Defineix una variable amb una ruta de fitxer, e.g.,
/var/log/apache2/error.log. - Extreu i mostra: el directori pare, el nom del fitxer complet i l’extensió.
- Usa mètodes de cadenes com
rfind()osplit().
Pista: el mètode
rfind()cerca un caràcter des del final de la cadena i retorna la seva posició. Això és útil per trobar l’últim/o l’últim.d’una ruta.
Resposta
Exemple d’script processa_ruta.py:
#!/usr/bin/env python3
"""Extreu les parts d'una ruta de fitxer."""
ruta = "/var/log/apache2/error.log"
# Trobar l'última barra per separar directori i fitxer
ultima_barra = ruta.rfind("/")
directori = ruta[:ultima_barra]
nom_fitxer = ruta[ultima_barra + 1:]
# Trobar l'últim punt per obtenir l'extensió
ultim_punt = nom_fitxer.rfind(".")
nom_sense_extensio = nom_fitxer[:ultim_punt]
extensio = nom_fitxer[ultim_punt + 1:]
# Mostrar resultats
print(f"Ruta completa: {ruta}")
print(f"Directori: {directori}")
print(f"Nom fitxer: {nom_fitxer}")
print(f"Nom base: {nom_sense_extensio}")
print(f"Extensió: {extensio}")Sortida esperada:
Ruta completa: /var/log/apache2/error.log
Directori: /var/log/apache2
Nom fitxer: error.log
Nom base: error
Extensió: logAlternativa usant split():
#!/usr/bin/env python3
"""Extreu les parts d'una ruta de fitxer (versió amb split)."""
ruta = "/var/log/apache2/error.log"
# Separar per barres
parts = ruta.split("/")
nom_fitxer = parts[-1] # Últim element
directori = "/".join(parts[:-1]) # Tot menys l'últim
# Separar nom i extensió
parts_nom = nom_fitxer.split(".")
extensio = parts_nom[-1]
nom_sense_extensio = ".".join(parts_nom[:-1])
print(f"Ruta completa: {ruta}")
print(f"Directori: {directori}")
print(f"Nom fitxer: {nom_fitxer}")
print(f"Nom base: {nom_sense_extensio}")
print(f"Extensió: {extensio}")Nota: en un programa real, usaríem el mòdul
pathlibque veurem més endavant. Proporciona mètodes específics per a aquesta tasca com.parent,.namei.suffix.
Exercici 4 #
Normalització de hostname
Objectiu: Netejar i normalitzar un hostname introduït per l’usuari.
- Crea un script anomenat
normalitza_hostname.py. - Demana a l’usuari que introdueixi un hostname.
- Normalitza el hostname: converteix a minúscules i elimina espais en blanc al principi i al final.
- Mostra el hostname original, el normalitzat i la seva longitud.
Pista: pots encadenar mètodes, e.g.,
text.strip().lower().
Resposta
Exemple d’script normalitza_hostname.py:
#!/usr/bin/env python3
"""Normalitza un hostname introduït per l'usuari."""
hostname_original = input("Introdueix un hostname: ")
# Normalitzar: eliminar espais i convertir a minúscules
hostname_net = hostname_original.strip().lower()
# Mostrar resultats
print()
print(f"Hostname original: '{hostname_original}'")
print(f"Hostname normalitzat: '{hostname_net}'")
print(f"Longitud: {len(hostname_net)} caràcters")Exemple d’execució:
Introdueix un hostname: WebServer01.Local
Hostname original: ' WebServer01.Local '
Hostname normalitzat: 'webserver01.local'
Longitud: 17 caràcters-
Els nombres de coma flotant funcionen de manera similar a la notació científica: la coma decimal no té una posició fixa, sinó que “flota” per adaptar-se a la magnitud del número. En anglès prové del terme floating point, ja que usen el punt com a separador decimal. ↩︎