---
title: ASIX M3. [UF2]. Abast i mutabilitat.
tags: asix, programació, funcions, programació modular
---
# ASIX1 M03: Programació bàsica
[vincle a font en MarkDown](https://hackmd.io/@JdaXaviQ/ryXvu18Zq)
---
# Abast i mutabilitat (scope)
## Abast
Quan treballem amb funcions no totes les variables es poden veure des de qualsevol part del programa. Al troç de programa on una variable és visible li diem '__abast__'.
Per exemple:
Una funció que definim dins d'una funció no la podem veure des de fora:
```python
def la_meva_funcio():
variable_interna = 5;
print(f"Dins de la funció: {variable_interna = }")
la_meva_funcio()
print(f"Fora de la funció: {variable_interna = }")
```
Dins de la funció: variable_interna = 5
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [1], in <module>
3 print(f"Dins de la funció: {variable_interna = }")
5 la_meva_funcio()
----> 6 print(f"Fora de la funció: {variable_interna = }")
NameError: name 'variable_interna' is not defined
Però dins de les funcions _si_ que podem veure les variables que s'han definit a fora:
```python
variable_externa = 5
def suma_interna_externa():
variable_interna = 3
print (f"{variable_interna + variable_externa = }")
suma_interna_externa()
```
## Mutabilitat
Segurament que hem sentit alguna vegada que Python és un programa orientat a objectes. Nosaltres de moment no sabem què és un objecte, però per a Python internament tots els tipus de dades són objectes i això vol dir que totes les variables tenen algunes coses en comú; per exemple a Python, totes les dades tenen una __identitat__, un __tipus__ i un __valor__.
Podem veure un exemple amb una variable de tipus __str__ i una altra de tipus __int__:
```python
def mutabilitat():
text = "foo, bar"
quantitat = 6
print(f"{id(text) = }")
print(f"{type(text) = }")
print(f"{text = }")
print("--- --- ---")
print(f"{id(quantitat) = }")
print(f"{type(quantitat) = }")
print(f"{quantitat = }")
mutabilitat()
```
Ara que coneixem que les dades a Python tenen tipus encara que no els hi diguem explícitament, hem de saber que alguns tipus de dades a Python són mutables i d'altres son inmutables i que això té implicacions a l'hora de passar les dades com a paràmetres a les nostres funcions o com a mínim a l'hora de tornar a utilitzar aquestes dades desprès d'haver passat per alguna funció.
### Alguns tipus de dades inmutables
* Booleans
* Tuples
* Enters
* Decimals de coma flotant
* Bytes
* Range
* Cadenes de text
### Alguns tipus de dades mutables
* Llistes
* Diccionaris
* Sets
Al següent exemple podem observar que si intentem modificar un nombre enter canvia la seva _id_, en realitat estem creant un nou objecte amb el nou valor, però que si modifiquem una llista la seva _id_ no canvia:
```python
x = 5
print(f"{id(x)=}", x)
x += 1
print(f"{id(x)=}", x)
```
```python
x = [5]
print(f"{id(x)=}", x)
x[0] += 1
print(f"{id(x)=}", x)
x.append(23)
print(f"{id(x)=}", x)
```
Aquesta característica que sembla anecdòtica, es torna important quan passem variables com a paràmetres a una funció. Observem el següent exemple:
```python
def incrementa_inmutable(x):
x += 1
return x
def incrementa_mutable(x):
x[0] += 1
return x
i = 9
m = [9]
incrementa_inmutable(i)
incrementa_mutable(m)
print(f"{i=}")
print(f"{m=}")
```
Aquest resultat que a primera vista pot semblar incoherent és el resultat intrínsec de que els objectes siguin mutables o inmutables.
Tornem a veure un altre cop l'exemple anterior, però aquesta vegada mostrant la id de les variables tan a dins com a fora de les funcions i abans i desprès de les modificacions:
```python
def incrementa_inmutable(x):
print(f"----- Dins de la funció (i): {id(x)=}")
x += 1
print(f"----- *Dins de la funció (i): {id(x)=}")
return x
def incrementa_mutable(x):
print(f"Dins de la funció (m): {id(x)=}")
x[0] += 1
print(f"*Dins de la funció (m): {id(x)=}")
return x
i = 9
m = [9]
print(f"----- Abans de la funció: {id(i)=}")
print(f"Abans de la funció: {id(m)=}")
incrementa_inmutable(i)
incrementa_mutable(m)
print(f"{i=}")
print(f"{m=}")
print(f"----- Desprès de la funció: {id(i)=}")
print(f"Desprès de la funció: {id(m)=}")
```
Podem observar que en el cas dels objectes inmutables que es modifiquen dins d'una funció, les modificacions es desen en un objecte diferent del que es passa per paràmetre i per tant no es poden veure fora de la funció que les ha modificat.