Commit 829731fd authored by jg5dev's avatar jg5dev 💬
Browse files

better

parent ad84aee3
Loading
Loading
Loading
Loading
+23 −0
Changes for src/apren/basics/advanced_python.md: 23 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -235,6 +235,29 @@ memoria[["cerca", "webhooks"]] = "…" # TypeError: unhashable type:
La clau pot ser-ho **perquè** és immutable. El mateix val per a un `@dataclass(frozen=True)`,
que és *hashable* precisament perquè ha renunciat a canviar.

### Heretar d'un tipus immutable: `__new__`

Instanciar té dos passos: `__new__` crea l'objecte i `__init__` l'inicialitza. Normalment n'hi ha prou amb `__init__`, però el contingut d'un tipus immutable es fixa en crear-lo: quan s'executa `__init__`, ja no es pot canviar. Per això una subclasse de `tuple`, `str` o `int` ha de definir `__new__`:

```python
class Point(tuple[int, int]):
    def __new__(cls, x: int, y: int) -> "Point":
        return super().__new__(cls, (x, y))

    @property
    def x(self) -> int:
        return self[0]

    @property
    def y(self) -> int:
        return self[1]

p = Point(3, 4)
print(p, p.x, isinstance(p, tuple))   # (3, 4) 3 True
```

`cls` indica quina classe cal construir: `tuple.__new__(Point, (3, 4))` crea un `Point`, no una tupla qualsevol. Objectes com `sys.version_info` són tuples amb noms d'aquest mateix estil. En codi propi, `@dataclass(frozen=True)` o `typing.NamedTuple` solen ser més simples.

### Mutabilitat a les biblioteques de dades

En càlcul numèric les dades són grans, i això capgira els costos: copiar un vector de
+2 −2
Changes for src/apren/basics/basic_python.md: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -718,7 +718,7 @@ print(s)
s = Student("Mary")
```

La PVM crida automàticament `__init__` en instanciar. L'argument `self` s'assigna automàticament a l'objecte nou. Les variables i paràmetres no tenen tipus; el tipus el té l'objecte al qual fan referència.
En instanciar, la PVM crea l'objecte nou amb `__new__` i després crida `__init__` per inicialitzar-lo, amb `self` referenciant aquest objecte. Gairebé mai cal definir `__new__`: només en subclasses de tipus immutables com `tuple` o `str`, perquè el seu contingut es fixa en crear l'objecte. Les variables i paràmetres no tenen tipus; el tipus el té l'objecte al qual fan referència.

### Visibilitat

@@ -1016,7 +1016,7 @@ for animal in animals:
    print(animal)
```

La subclasse pot cridar el constructor del pare amb `super()`:
La subclasse pot cridar el mètode `__init__` del pare amb `super()`:

```python
class Dog(Animal):