Vés al contingut

Python 3 per a no programadors/La venjança dels Strings

Tot seguit es presenta un bon truc que es pot fer amb les cadenes:

def lletreja(cadena):
    for caracter in cadena:
        print(u"Dóna'm una " + caracter)
        print("'" + caracter + "'")

lletreja("Prou")

def mig(cadena):
    print(u"El caràcter del mig és:", cadena[len(cadena) // 2])

mig("abcdefg")
mig(u"Llenguatge de programació Python")
mig("Barcelona")

I el resultat és:

Dóna'm una P
'P'
Dóna'm una r
'r'
Dóna'm una o
'o'
Dóna'm una u
'u'
El caràcter del mig és: d
El caràcter del mig és: r
El caràcter del mig és: e

El que demostra aquest programa és que les cadenes són semblants a les llistes de diverses maneres. La funció lletreja() mostra que es poden fer servir els bucles for amb cadenes tal com es poden fer servir amb llistes. La funció mig() mostra que les cadenes també poden fer servir la funció len() així com índex de llistes i llesques. La majoria de les característiques de les llistes també funcionen amb les cadenes.

El següent programa demostra algunes característiques específiques de les cadenes:

def passa_a_majuscules(cadena):
    ## Transforma una cadena passant tots els caràcters a majúscules
    majuscula = ""
    for caracter in cadena:
        if 'a' <= caracter <= 'z':
            lloc = ord(caracter) - ord('a')
            nou_ascii = lloc + ord('A')
            caracter = chr(nou_ascii)
        majuscula = majuscula + caracter
    return majuscula

print(passa_a_majuscules("Un text qualsevol"))

la sortida és:

UN TEXT QUALSEVOL

Això funciona perquè l'ordinador representa els caràcters d'una cadena com a números de 0 fins a 1.114.111. Per exemple 'A' és 65, 'B' és 66 i א és 1488. Els valors són els codis unicode. Python té una funció anomenada ord() (abreviatura de ordinal) que retorna el codi d'un caràcter. També hi ha la funció inversa corresponent anomenada chr() que transforma un número en el caràcter que codifica. Tenint això en ment, el programa hauria de començar a quedar clar. El primer detall és la instrucció: if 'a' <= caracter <= 'z': que comprova que el caràcter sigui una lletra minúscula. Si ho és llavors s'executen les línies següents. Primer es transforma en la seva posició relativa a la lletra a amb la instrucció lloc = ord(caracter) - ord('a') de manera que a = 0, b = 1, c = 2 i així. Tot seguit es troba el nou valor amb la instrucció nou_ascii = lloc + ord('A'). Aquest valor es torna a convertir en un caràcter que ara serà una lletra majúscula. Tingueu en compte que a la pràctica s'ha de fer això, s'ha de fer servir majuscula=caracter.upper() que també funciona pels caràcters especials com les lletres amb accent o dièresi i per tots els idiomes.

Ara alguns exercicis interactius:

>>> # Enter a cadena
>>> 2
2
>>> repr(2)
'2'
>>> -123
-123
>>> repr(-123)
'-123'
>>> `123`
'123'
>>> # Cadena a enter
>>> "23"
'23'
>>> int("23")
23
>>> "23" * 2
'2323'
>>> int("23") * 2
46
>>> # Coma flotant a cadena
>>> 1.23
1.23
>>> repr(1.23)
'1.23'
>>> # Coma flotant a enter
>>> 1.23
1.23
>>> int(1.23)
1
>>> int(-1.23)
-1
>>> # Cadena a coma flotant
>>> float("1.23")
1.23
>>> "1.23" 
'1.23'
>>> float("123")
123.0
>>> `float("1.23")`
'1.23'

Si encara no ho heu endevinat, la funció repr() transforma enters a cadenes i la funció int() transforma cadenes a enters. La funció float() transforma cadenes a nombres de coma flotant. la funció repr() retorna una representació imprimible (una cadena) d'alguna cosa. `...` també transforma gairebé qualsevol cosa en una cadena. Aquí hi ha alguns exemples:

>>> repr(1)
'1'
>>> repr(234.14)
'234.14'
>>> repr([4, 42, 10])
'[4, 42, 10]'
>>> `[4, 42, 10]`
'[4, 42, 10]'

La funció int() intenta convertir una cadena (o un nombre de coma flotant) en un enter. També hi ha una funció similar anomenada float() que transforma un enter o una cadena en un nombre de coma flotant. Un altre funció que té Python és la funció eval(). La funció eval() agafa una cadena i retorna una dada del tipus que Python pensa que ha trobat. Per exemple:

>>> v = eval('123')
>>> print(v, type(v))
123 <type 'int'>
>>> v = eval('645.123')
>>> print(v, type(v))
645.123 <type 'float'>
>>> v = eval('[1, 2, 3]')
>>> print(v, type(v))
[1, 2, 3] <type 'list'>

Si feu servir la funció eval() us heu d'assegurar que retorna el tipus que espereu.

Una funció de cadena útil és el mètode split(). Eus aquí un exemple:

>>> u"Això és un grapat de paraules".split()
['Això', 'és', 'un', 'grapat', 'de', 'paraules']
>>> text = "Primer lot, segon lot, tercer, quart"
>>> text.split(",")
['Primer lot', ' segon lot', ' tercer', ' quart']

Fixeu-vos que split() transforma una cadena en una llista de cadenes. Per omissió la cadena es parteix pels espais altrament per la cadena que s'hagi entrat com a argument opcional (en aquest cas una coma). També es pot afegir un altre argument que indica quantes vegades es farà servir el separador per partir el text. Per exemple:

>>> list = text.split(",")
>>> len(list)
4
>>> list[-1]
' quart'
>>> list = text.split(",", 2)
>>> len(list)
3
>>> list[-1]
' tercer, quart'

Llescar cadenes (i llistes)

[modifica]

Les cadenes es poden talar a bocins — de la mateixa manera que es va explicar alcapítol anterior per a les llistes — fent servir l'"operador" per llescar []. L'operador per llescar funciona de la mateixa manera d'abans: text[primer_index:últim_index] (en casos molt rars hi pot haver uns altres dos punts i un tercer argument, com a l'exemple que es presenta abaix).

Per tal de no confondre's pels nombres d'índex, és més fàcils veure'ls com a llocs de tall, possibilitats de tallar una cadena en bocins. Aquí hi ha un exemple que mostra els llocs de tall (de groc) i els seus nombres d'índex (vermell i blau) per a una cadenade text senzilla:

0 1 2 ... -2 -1
text = " C A D E N A "
[: :]

Fixeu-vos que els índexs vermells compten des del començament de la cadena i els blaus des del final cap enrere. (fixeu-vos que no existeix el balu -0, cosa que podria semblar lògica al final de la cadena. Això és degut al fet que -0 == 0, -0 també vol dir "començament de la cadena".) Ara ja esteu preparats per fer servir els índexs en operacions de llescar.

text[1:4] "CAD"
text[:5] "CADEN"
text[:-1] "CADEN"
text[-4:] "DENA"
text[2] "N"
text[:] "CADENA"
text[::-1] "ANEDAC"

text[1:4] dóna tot el text de la cadena entre els llocs de tall 1 i 4, "CAD". Si s'omet un dels arguments [primer_índex:últim_índex], per omissió s'obté el començament o el final de la cadena: text[:5] dóna "CADEN". Tant pel primer_índex com per l'últim_índex es poden fer servir tant el mètode de numeració vermell com el blau: text[:-1] dóna el mateix que text[:5], perquè en aquest cas l'índex -1 és al mateix lloc que el 5. Si no es fa servir un argument i dos punts, el nombre es tracta d'una manera diferent: text[2] dóna un únic caràcter que és el que es troba darrere del segon lloc de tall, "N". L'operador de llescar especial text[:] vol dir "del començament al final" i genera ua còpia de tota la cadena (o llista, com s'ha vist al capítol anterior).

Per acabar i no menys important, l'operació de llescar pot tenir un segon símbol de dos punts i un tercer argument, que s'interpreta com "mida del pas": text[::-1] és text del començament al final, amb una mida de pas de -1. -1 vol dir "cada caràcter, però al reves". "CADENA" al revés és "ANEDAC" (proveu una mida de pas de 2, si no heu agafat que farà).

Totes aquestes operacions de llescar també funcionen amb llistes. En aquest sentit les cadenes son només un cas especial de llistes, on els elements de la llista són caràcters. Només cal recordar el concepte de llocs de tall i els índexs per llescar coses seran molt menys confosos.

Exemples

[modifica]
# Aquest programa requereix una comprensió alta dels nombres decimals
def to_string(in_int):
    """Converteix un integer a string"""
    out_str = ""
    prefix = ""
    if in_int < 0:
        prefix = "-"
        in_int = -in_int
    while in_int // 10 != 0:
        out_str = str(in_int % 10) + out_str
        in_int = in_int // 10
    out_str = str(in_int % 10) + out_str
    return prefix + out_str

def to_int(in_str):
    """Converteix un string a integer"""
    out_num = 0
    if in_str[0] == "-":
        multiplier = -1
        in_str = in_str[1:]
    else:
        multiplier = 1
    for c in in_str:
        out_num = out_num * 10 + int(c)
    return out_num * multiplier

print(to_string(2))
print(to_string(23445))
print(to_string(-23445))
print(to_int("14234"))
print(to_int("12345"))
print(to_int("-3512"))

El resultat és:

2
23445
-23445
14234
12345
-3512