From fb47609021e2a8890559862032c0b54c30b05829 Mon Sep 17 00:00:00 2001 From: Ekaitz Zarraga Date: Sun, 1 Dec 2019 16:38:18 +0100 Subject: Add some protocols --- src/05_oop.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) (limited to 'src/05_oop.md') diff --git a/src/05_oop.md b/src/05_oop.md index 816fd99..5e8f2c4 100644 --- a/src/05_oop.md +++ b/src/05_oop.md @@ -519,14 +519,85 @@ clase que defina un objeto en el que se puede buscar necesitas que sea un ### *Representable*: `__repr__` +Este protocolo sirve para otorgar a python una forma de representar estos +objetos. Al ejecutar la función `print` o al exponer valores en la REPL +(recuerda que la P significa print), python trata de visualizarlos. + +La el método `__repr__` se ejecuta justo antes de imprimirse el objeto, de +forma automática. La función requiere que se devuelva un elemento de tipo +string, que será el que después se visualice. + +En el ejemplo a continuación se comienza con la clase `Dog` vacía y se +visualiza una de sus instancias. Posteriormente, se reasigna la función +`__repr__` de `Dog` con una función que devuelve un string. Al volver a mostrar +a `bobby` el resultado cambia. + +Como se ve en el ejemplo, es interesante tener una buena función de +representación si lo que se pretende es entender el contenido de los objetos. + +> NOTA: Python ya aporta una forma estándar de representar los objetos, si la +> función `__repr__` no se define simplemente se usará la forma estándar. + +``` python +>>> class Dog: +... pass +... +>>> bobby = Dog() +>>> bobby +<__main__.Dog object at 0x7fb7fba1b908> + +>>> Dog.__repr__ = lambda self: "Dog called: " + self.name +>>> bobby.name = "Bobby" +>>> bobby +Dog called: Bobby +>>> +``` + ### *Contable*: `__len__` +En python se utiliza la función `len` para comprobar la longitud de cualquier +elemento contable. Por ejemplo: + +``` python +>>> len( (1,2,3) ) +3 +``` + +Las objetos que soporten esta función podrán contarse para conocer su longitud +mediante la función `len`. Python llamará al método `__len__` del objeto (que +se espera que devuelva un número entero) y ésta será su longitud. Siguiendo con +el ejemplo del protocolo anterior: + +``` python +>>> Dog.__len__ = lambda self: 12 # Siempre devuelve 12 +>>> len(bobby) +12 +``` + +Este protocolo permite crear elementos contables, en lugar de los típicos +diccionario, tupla y lista. Como por ejemplo los ya existentes `NamedTuple`, +`OrderedDict` y otros. Los protocolos para el *buscable* e *iterable* también +son muy interesantes para esta labor. + ### *Buscable*: `__contains__` -### *Creable*: `__init__` +El método `__contains__` debe devolver `True` o `False` y recibir un argumento +de entrada. Con esto el objeto será capaz de comprobarse con sentencias que +hagan uso del operador `in` (y `not in`). Las dos llamadas del ejemplo son +equivalentes. La segunda es lo que python realiza internamente al encontrarse +el operador `in` o el operador `not in`. + +``` python +>>> 1 in [1,2,3] +True +>>> [1,2,3].__contains__(1) +True +``` ### *Iterable*: `__next__` e `__iter__` +### *Creable*: `__init__` + ### *Abrible* y *cerrable*: `__enter__` y `__exit__` Que funcionen con el `with` -- cgit v1.2.3