Capítulo 6: Programación Orientada a Objetos en Python
6.3 Funciones Especiales de Python
Sumergámonos en las funciones especiales en Python, también conocidas como métodos "mágicos" o "dunder". Estos métodos proporcionan una forma simple de hacer que tus clases actúen como tipos integrados. Esto significa que puedes usar funciones específicas del tipo (como len
o +
) con tus objetos. Ya has visto estos en uso con el método __init__
para clases. ¡Explorémoslos más:
1. Métodos __str__
y __repr__
Los métodos __str__
y __repr__
en Python representan los objetos de la clase como una cadena: son métodos para la representación de una clase como una cadena. El método __str__
en Python representa los objetos de la clase como una cadena legible para humanos, mientras que el método __repr__
está destinado a ser una representación no ambigua del objeto, y idealmente debería contener más detalles que __str__
. Si se define __repr__
y no __str__
, los objetos se comportarán como si __str__=__repr__
.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'Employee[name={self.name}, age={self.age}]'
def __repr__(self):
return f'{self.__class__.__name__}({self.name!r}, {self.age!r})'
emp = Employee('John Doe', 30)
print(str(emp)) # Employee[name=John Doe, age=30]
print(repr(emp)) # Employee('John Doe', 30)
2. Métodos __add__
y __sub__
Estos métodos se utilizan para sobrecargar los operadores +
y -
.
class Complex:
def __init__(self, real, imag):
self.real = real
self.imag = imag
def __add__(self, other):
return Complex(self.real + other.real, self.imag + other.imag)
def __sub__(self, other):
return Complex(self.real - other.real, self.imag - other.imag)
def __str__(self):
return f'{self.real} + {self.imag}i'
c1 = Complex(1, 2)
c2 = Complex(2, 3)
c3 = c1 + c2
c4 = c1 - c2
print(c3) # 3 + 5i
print(c4) # -1 - 1i
3. Método __len__
El método __len__
devuelve la longitud (el número de elementos) de un objeto. El método solo debería ser implementado para clases que sean colecciones.
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def __len__(self):
return len(self.items)
s = Stack()
s.push('Hello')
s.push('World')
print(len(s)) # 2
4. Métodos __getitem__
y __setitem__
El método __getitem__
se utiliza para implementar self[key] para acceso. Del mismo modo, __setitem__
se utiliza para la asignación a self[key].
class CustomDict:
def __init__(self, items):
self.items = items
def __getitem__(self, key):
return self.items[key]
def __setitem__(self, key, value):
self.items[key] = value
custom_dict = CustomDict({'one': 1, 'two': 2})
print(custom_dict['one']) # 1
custom_dict['three'] = 3
print(custom_dict['three']) # 3
5. Métodos __eq__
y __ne__
Estos métodos se utilizan para sobrecargar los operadores (==) y (!=) respectivamente.
class Employee:
def __init__(self, name, id):
self.name = name
self.id = id
def __eq__(self, other):
return self.id == other.id
def __ne__(self, other):
return self.id != other.id
emp1 = Employee('John', 'E101')
emp2 = Employee('Jane', 'E102')
emp3 = Employee('David', 'E101')
print(emp1 == emp2) # False
print(emp1 == emp3) # True
print(emp1 != emp3) # False
6. Método __del__
El método __del__
es conocido como un método destructor en Python. Se llama cuando todas las referencias al objeto han sido eliminadas, es decir, cuando un objeto es recolectado por el recolector de basura.
class Test:
def __init__(self):
print('Constructor Executed')
def __del__(self):
print('Destructor Executed')
t1 = Test() # Constructor Executed
t1 = None # Destructor Executed
Como puedes ver, los métodos mágicos son la clave para el uso efectivo del paradigma de programación orientada a objetos en Python, lo que te permite definir comportamientos para clases personalizadas que son intuitivas de entender y fáciles de usar.
Decoradores en Python
De hecho, hay otro concepto de Python que podría ser interesante discutir en este capítulo: los decoradores en Python, que pueden ser muy útiles cuando deseas cambiar el comportamiento de un método sin cambiar su código fuente.
Un decorador en Python es una herramienta poderosa que ayuda a los desarrolladores a modificar el comportamiento de una función, método o definición de clase sin tener que reescribir todo el código. Es una función de orden superior que toma otra función como argumento y devuelve una versión modificada de ella.
El decorador modifica el objeto original, que se le pasa como argumento, y devuelve una versión actualizada que está vinculada al nombre utilizado en la definición. Los decoradores se utilizan ampliamente en la comunidad de Python y son una característica clave del lenguaje que permite a los desarrolladores escribir un código más conciso y elegante.
Son particularmente útiles cuando se trabaja con bases de código grandes, ya que permiten a los desarrolladores realizar cambios en el comportamiento de una función sin tener que modificar su implementación. Además, los decoradores se pueden utilizar para agregar nueva funcionalidad a una función, como registro, almacenamiento en caché o autenticación, sin tener que modificar su código fuente.
En general, los decoradores son una herramienta poderosa que puede ayudar a los desarrolladores a escribir un código más eficiente y mantenible en Python.
Ejemplo:
Aquí tienes un ejemplo básico de un decorador en Python:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Cuando ejecutas este código, verás:hen you run this code, you'll see:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
En el ejemplo anterior, @my_decorator
es un decorador. Las funciones que toman otras funciones como argumentos también se llaman funciones de orden superior. En este caso, my_decorator
es una función de orden superior.
El símbolo @
es solo azúcar sintáctica que nos permite aplicar fácilmente un decorador a una función. La línea @my_decorator
es equivalente a say_hello = my_decorator(say_hello)
.
Esto puede ser mucho para asimilar si eres nuevo en los decoradores. No te preocupes. Los decoradores son una herramienta poderosa en Python, pero pueden ser un poco difíciles de entender al principio. Simplemente tómate tu tiempo con este concepto, juega un poco con algunos ejemplos y le tomarás la mano.
El concepto de decoradores abre todo un nuevo mundo de posibilidades en Python. Se pueden utilizar para registro, aplicación de control de acceso y autenticación, limitación de velocidad, almacenamiento en caché y mucho más.
Los fabricantes de decoradores se pueden utilizar cuando deseas usar un decorador, pero necesitas proporcionarle argumentos. Un fabricante de decoradores es una función que devuelve un decorador. Así es cómo puedes crear uno:
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
greet("World")
En este ejemplo, repeat(num_times=3)
devuelve un decorador que repetirá la función decorada tres veces. Esto se llama un fabricante de decoradores.
Cuando ejecutas este código, verás:
Hello World
Hello World
Hello World
Como puedes ver, la función greet fue llamada tres veces.
Este es un uso más avanzado de los decoradores, pero una vez que los entiendes, pueden ser increíblemente poderosos y ayudar a que tu código sea más legible y mantenible. La capacidad de modificar el comportamiento de una función de una manera tan limpia y legible es una de las cosas que hace que Python sea un gran lenguaje para trabajar.
6.3 Funciones Especiales de Python
Sumergámonos en las funciones especiales en Python, también conocidas como métodos "mágicos" o "dunder". Estos métodos proporcionan una forma simple de hacer que tus clases actúen como tipos integrados. Esto significa que puedes usar funciones específicas del tipo (como len
o +
) con tus objetos. Ya has visto estos en uso con el método __init__
para clases. ¡Explorémoslos más:
1. Métodos __str__
y __repr__
Los métodos __str__
y __repr__
en Python representan los objetos de la clase como una cadena: son métodos para la representación de una clase como una cadena. El método __str__
en Python representa los objetos de la clase como una cadena legible para humanos, mientras que el método __repr__
está destinado a ser una representación no ambigua del objeto, y idealmente debería contener más detalles que __str__
. Si se define __repr__
y no __str__
, los objetos se comportarán como si __str__=__repr__
.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'Employee[name={self.name}, age={self.age}]'
def __repr__(self):
return f'{self.__class__.__name__}({self.name!r}, {self.age!r})'
emp = Employee('John Doe', 30)
print(str(emp)) # Employee[name=John Doe, age=30]
print(repr(emp)) # Employee('John Doe', 30)
2. Métodos __add__
y __sub__
Estos métodos se utilizan para sobrecargar los operadores +
y -
.
class Complex:
def __init__(self, real, imag):
self.real = real
self.imag = imag
def __add__(self, other):
return Complex(self.real + other.real, self.imag + other.imag)
def __sub__(self, other):
return Complex(self.real - other.real, self.imag - other.imag)
def __str__(self):
return f'{self.real} + {self.imag}i'
c1 = Complex(1, 2)
c2 = Complex(2, 3)
c3 = c1 + c2
c4 = c1 - c2
print(c3) # 3 + 5i
print(c4) # -1 - 1i
3. Método __len__
El método __len__
devuelve la longitud (el número de elementos) de un objeto. El método solo debería ser implementado para clases que sean colecciones.
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def __len__(self):
return len(self.items)
s = Stack()
s.push('Hello')
s.push('World')
print(len(s)) # 2
4. Métodos __getitem__
y __setitem__
El método __getitem__
se utiliza para implementar self[key] para acceso. Del mismo modo, __setitem__
se utiliza para la asignación a self[key].
class CustomDict:
def __init__(self, items):
self.items = items
def __getitem__(self, key):
return self.items[key]
def __setitem__(self, key, value):
self.items[key] = value
custom_dict = CustomDict({'one': 1, 'two': 2})
print(custom_dict['one']) # 1
custom_dict['three'] = 3
print(custom_dict['three']) # 3
5. Métodos __eq__
y __ne__
Estos métodos se utilizan para sobrecargar los operadores (==) y (!=) respectivamente.
class Employee:
def __init__(self, name, id):
self.name = name
self.id = id
def __eq__(self, other):
return self.id == other.id
def __ne__(self, other):
return self.id != other.id
emp1 = Employee('John', 'E101')
emp2 = Employee('Jane', 'E102')
emp3 = Employee('David', 'E101')
print(emp1 == emp2) # False
print(emp1 == emp3) # True
print(emp1 != emp3) # False
6. Método __del__
El método __del__
es conocido como un método destructor en Python. Se llama cuando todas las referencias al objeto han sido eliminadas, es decir, cuando un objeto es recolectado por el recolector de basura.
class Test:
def __init__(self):
print('Constructor Executed')
def __del__(self):
print('Destructor Executed')
t1 = Test() # Constructor Executed
t1 = None # Destructor Executed
Como puedes ver, los métodos mágicos son la clave para el uso efectivo del paradigma de programación orientada a objetos en Python, lo que te permite definir comportamientos para clases personalizadas que son intuitivas de entender y fáciles de usar.
Decoradores en Python
De hecho, hay otro concepto de Python que podría ser interesante discutir en este capítulo: los decoradores en Python, que pueden ser muy útiles cuando deseas cambiar el comportamiento de un método sin cambiar su código fuente.
Un decorador en Python es una herramienta poderosa que ayuda a los desarrolladores a modificar el comportamiento de una función, método o definición de clase sin tener que reescribir todo el código. Es una función de orden superior que toma otra función como argumento y devuelve una versión modificada de ella.
El decorador modifica el objeto original, que se le pasa como argumento, y devuelve una versión actualizada que está vinculada al nombre utilizado en la definición. Los decoradores se utilizan ampliamente en la comunidad de Python y son una característica clave del lenguaje que permite a los desarrolladores escribir un código más conciso y elegante.
Son particularmente útiles cuando se trabaja con bases de código grandes, ya que permiten a los desarrolladores realizar cambios en el comportamiento de una función sin tener que modificar su implementación. Además, los decoradores se pueden utilizar para agregar nueva funcionalidad a una función, como registro, almacenamiento en caché o autenticación, sin tener que modificar su código fuente.
En general, los decoradores son una herramienta poderosa que puede ayudar a los desarrolladores a escribir un código más eficiente y mantenible en Python.
Ejemplo:
Aquí tienes un ejemplo básico de un decorador en Python:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Cuando ejecutas este código, verás:hen you run this code, you'll see:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
En el ejemplo anterior, @my_decorator
es un decorador. Las funciones que toman otras funciones como argumentos también se llaman funciones de orden superior. En este caso, my_decorator
es una función de orden superior.
El símbolo @
es solo azúcar sintáctica que nos permite aplicar fácilmente un decorador a una función. La línea @my_decorator
es equivalente a say_hello = my_decorator(say_hello)
.
Esto puede ser mucho para asimilar si eres nuevo en los decoradores. No te preocupes. Los decoradores son una herramienta poderosa en Python, pero pueden ser un poco difíciles de entender al principio. Simplemente tómate tu tiempo con este concepto, juega un poco con algunos ejemplos y le tomarás la mano.
El concepto de decoradores abre todo un nuevo mundo de posibilidades en Python. Se pueden utilizar para registro, aplicación de control de acceso y autenticación, limitación de velocidad, almacenamiento en caché y mucho más.
Los fabricantes de decoradores se pueden utilizar cuando deseas usar un decorador, pero necesitas proporcionarle argumentos. Un fabricante de decoradores es una función que devuelve un decorador. Así es cómo puedes crear uno:
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
greet("World")
En este ejemplo, repeat(num_times=3)
devuelve un decorador que repetirá la función decorada tres veces. Esto se llama un fabricante de decoradores.
Cuando ejecutas este código, verás:
Hello World
Hello World
Hello World
Como puedes ver, la función greet fue llamada tres veces.
Este es un uso más avanzado de los decoradores, pero una vez que los entiendes, pueden ser increíblemente poderosos y ayudar a que tu código sea más legible y mantenible. La capacidad de modificar el comportamiento de una función de una manera tan limpia y legible es una de las cosas que hace que Python sea un gran lenguaje para trabajar.
6.3 Funciones Especiales de Python
Sumergámonos en las funciones especiales en Python, también conocidas como métodos "mágicos" o "dunder". Estos métodos proporcionan una forma simple de hacer que tus clases actúen como tipos integrados. Esto significa que puedes usar funciones específicas del tipo (como len
o +
) con tus objetos. Ya has visto estos en uso con el método __init__
para clases. ¡Explorémoslos más:
1. Métodos __str__
y __repr__
Los métodos __str__
y __repr__
en Python representan los objetos de la clase como una cadena: son métodos para la representación de una clase como una cadena. El método __str__
en Python representa los objetos de la clase como una cadena legible para humanos, mientras que el método __repr__
está destinado a ser una representación no ambigua del objeto, y idealmente debería contener más detalles que __str__
. Si se define __repr__
y no __str__
, los objetos se comportarán como si __str__=__repr__
.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'Employee[name={self.name}, age={self.age}]'
def __repr__(self):
return f'{self.__class__.__name__}({self.name!r}, {self.age!r})'
emp = Employee('John Doe', 30)
print(str(emp)) # Employee[name=John Doe, age=30]
print(repr(emp)) # Employee('John Doe', 30)
2. Métodos __add__
y __sub__
Estos métodos se utilizan para sobrecargar los operadores +
y -
.
class Complex:
def __init__(self, real, imag):
self.real = real
self.imag = imag
def __add__(self, other):
return Complex(self.real + other.real, self.imag + other.imag)
def __sub__(self, other):
return Complex(self.real - other.real, self.imag - other.imag)
def __str__(self):
return f'{self.real} + {self.imag}i'
c1 = Complex(1, 2)
c2 = Complex(2, 3)
c3 = c1 + c2
c4 = c1 - c2
print(c3) # 3 + 5i
print(c4) # -1 - 1i
3. Método __len__
El método __len__
devuelve la longitud (el número de elementos) de un objeto. El método solo debería ser implementado para clases que sean colecciones.
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def __len__(self):
return len(self.items)
s = Stack()
s.push('Hello')
s.push('World')
print(len(s)) # 2
4. Métodos __getitem__
y __setitem__
El método __getitem__
se utiliza para implementar self[key] para acceso. Del mismo modo, __setitem__
se utiliza para la asignación a self[key].
class CustomDict:
def __init__(self, items):
self.items = items
def __getitem__(self, key):
return self.items[key]
def __setitem__(self, key, value):
self.items[key] = value
custom_dict = CustomDict({'one': 1, 'two': 2})
print(custom_dict['one']) # 1
custom_dict['three'] = 3
print(custom_dict['three']) # 3
5. Métodos __eq__
y __ne__
Estos métodos se utilizan para sobrecargar los operadores (==) y (!=) respectivamente.
class Employee:
def __init__(self, name, id):
self.name = name
self.id = id
def __eq__(self, other):
return self.id == other.id
def __ne__(self, other):
return self.id != other.id
emp1 = Employee('John', 'E101')
emp2 = Employee('Jane', 'E102')
emp3 = Employee('David', 'E101')
print(emp1 == emp2) # False
print(emp1 == emp3) # True
print(emp1 != emp3) # False
6. Método __del__
El método __del__
es conocido como un método destructor en Python. Se llama cuando todas las referencias al objeto han sido eliminadas, es decir, cuando un objeto es recolectado por el recolector de basura.
class Test:
def __init__(self):
print('Constructor Executed')
def __del__(self):
print('Destructor Executed')
t1 = Test() # Constructor Executed
t1 = None # Destructor Executed
Como puedes ver, los métodos mágicos son la clave para el uso efectivo del paradigma de programación orientada a objetos en Python, lo que te permite definir comportamientos para clases personalizadas que son intuitivas de entender y fáciles de usar.
Decoradores en Python
De hecho, hay otro concepto de Python que podría ser interesante discutir en este capítulo: los decoradores en Python, que pueden ser muy útiles cuando deseas cambiar el comportamiento de un método sin cambiar su código fuente.
Un decorador en Python es una herramienta poderosa que ayuda a los desarrolladores a modificar el comportamiento de una función, método o definición de clase sin tener que reescribir todo el código. Es una función de orden superior que toma otra función como argumento y devuelve una versión modificada de ella.
El decorador modifica el objeto original, que se le pasa como argumento, y devuelve una versión actualizada que está vinculada al nombre utilizado en la definición. Los decoradores se utilizan ampliamente en la comunidad de Python y son una característica clave del lenguaje que permite a los desarrolladores escribir un código más conciso y elegante.
Son particularmente útiles cuando se trabaja con bases de código grandes, ya que permiten a los desarrolladores realizar cambios en el comportamiento de una función sin tener que modificar su implementación. Además, los decoradores se pueden utilizar para agregar nueva funcionalidad a una función, como registro, almacenamiento en caché o autenticación, sin tener que modificar su código fuente.
En general, los decoradores son una herramienta poderosa que puede ayudar a los desarrolladores a escribir un código más eficiente y mantenible en Python.
Ejemplo:
Aquí tienes un ejemplo básico de un decorador en Python:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Cuando ejecutas este código, verás:hen you run this code, you'll see:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
En el ejemplo anterior, @my_decorator
es un decorador. Las funciones que toman otras funciones como argumentos también se llaman funciones de orden superior. En este caso, my_decorator
es una función de orden superior.
El símbolo @
es solo azúcar sintáctica que nos permite aplicar fácilmente un decorador a una función. La línea @my_decorator
es equivalente a say_hello = my_decorator(say_hello)
.
Esto puede ser mucho para asimilar si eres nuevo en los decoradores. No te preocupes. Los decoradores son una herramienta poderosa en Python, pero pueden ser un poco difíciles de entender al principio. Simplemente tómate tu tiempo con este concepto, juega un poco con algunos ejemplos y le tomarás la mano.
El concepto de decoradores abre todo un nuevo mundo de posibilidades en Python. Se pueden utilizar para registro, aplicación de control de acceso y autenticación, limitación de velocidad, almacenamiento en caché y mucho más.
Los fabricantes de decoradores se pueden utilizar cuando deseas usar un decorador, pero necesitas proporcionarle argumentos. Un fabricante de decoradores es una función que devuelve un decorador. Así es cómo puedes crear uno:
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
greet("World")
En este ejemplo, repeat(num_times=3)
devuelve un decorador que repetirá la función decorada tres veces. Esto se llama un fabricante de decoradores.
Cuando ejecutas este código, verás:
Hello World
Hello World
Hello World
Como puedes ver, la función greet fue llamada tres veces.
Este es un uso más avanzado de los decoradores, pero una vez que los entiendes, pueden ser increíblemente poderosos y ayudar a que tu código sea más legible y mantenible. La capacidad de modificar el comportamiento de una función de una manera tan limpia y legible es una de las cosas que hace que Python sea un gran lenguaje para trabajar.
6.3 Funciones Especiales de Python
Sumergámonos en las funciones especiales en Python, también conocidas como métodos "mágicos" o "dunder". Estos métodos proporcionan una forma simple de hacer que tus clases actúen como tipos integrados. Esto significa que puedes usar funciones específicas del tipo (como len
o +
) con tus objetos. Ya has visto estos en uso con el método __init__
para clases. ¡Explorémoslos más:
1. Métodos __str__
y __repr__
Los métodos __str__
y __repr__
en Python representan los objetos de la clase como una cadena: son métodos para la representación de una clase como una cadena. El método __str__
en Python representa los objetos de la clase como una cadena legible para humanos, mientras que el método __repr__
está destinado a ser una representación no ambigua del objeto, y idealmente debería contener más detalles que __str__
. Si se define __repr__
y no __str__
, los objetos se comportarán como si __str__=__repr__
.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f'Employee[name={self.name}, age={self.age}]'
def __repr__(self):
return f'{self.__class__.__name__}({self.name!r}, {self.age!r})'
emp = Employee('John Doe', 30)
print(str(emp)) # Employee[name=John Doe, age=30]
print(repr(emp)) # Employee('John Doe', 30)
2. Métodos __add__
y __sub__
Estos métodos se utilizan para sobrecargar los operadores +
y -
.
class Complex:
def __init__(self, real, imag):
self.real = real
self.imag = imag
def __add__(self, other):
return Complex(self.real + other.real, self.imag + other.imag)
def __sub__(self, other):
return Complex(self.real - other.real, self.imag - other.imag)
def __str__(self):
return f'{self.real} + {self.imag}i'
c1 = Complex(1, 2)
c2 = Complex(2, 3)
c3 = c1 + c2
c4 = c1 - c2
print(c3) # 3 + 5i
print(c4) # -1 - 1i
3. Método __len__
El método __len__
devuelve la longitud (el número de elementos) de un objeto. El método solo debería ser implementado para clases que sean colecciones.
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def __len__(self):
return len(self.items)
s = Stack()
s.push('Hello')
s.push('World')
print(len(s)) # 2
4. Métodos __getitem__
y __setitem__
El método __getitem__
se utiliza para implementar self[key] para acceso. Del mismo modo, __setitem__
se utiliza para la asignación a self[key].
class CustomDict:
def __init__(self, items):
self.items = items
def __getitem__(self, key):
return self.items[key]
def __setitem__(self, key, value):
self.items[key] = value
custom_dict = CustomDict({'one': 1, 'two': 2})
print(custom_dict['one']) # 1
custom_dict['three'] = 3
print(custom_dict['three']) # 3
5. Métodos __eq__
y __ne__
Estos métodos se utilizan para sobrecargar los operadores (==) y (!=) respectivamente.
class Employee:
def __init__(self, name, id):
self.name = name
self.id = id
def __eq__(self, other):
return self.id == other.id
def __ne__(self, other):
return self.id != other.id
emp1 = Employee('John', 'E101')
emp2 = Employee('Jane', 'E102')
emp3 = Employee('David', 'E101')
print(emp1 == emp2) # False
print(emp1 == emp3) # True
print(emp1 != emp3) # False
6. Método __del__
El método __del__
es conocido como un método destructor en Python. Se llama cuando todas las referencias al objeto han sido eliminadas, es decir, cuando un objeto es recolectado por el recolector de basura.
class Test:
def __init__(self):
print('Constructor Executed')
def __del__(self):
print('Destructor Executed')
t1 = Test() # Constructor Executed
t1 = None # Destructor Executed
Como puedes ver, los métodos mágicos son la clave para el uso efectivo del paradigma de programación orientada a objetos en Python, lo que te permite definir comportamientos para clases personalizadas que son intuitivas de entender y fáciles de usar.
Decoradores en Python
De hecho, hay otro concepto de Python que podría ser interesante discutir en este capítulo: los decoradores en Python, que pueden ser muy útiles cuando deseas cambiar el comportamiento de un método sin cambiar su código fuente.
Un decorador en Python es una herramienta poderosa que ayuda a los desarrolladores a modificar el comportamiento de una función, método o definición de clase sin tener que reescribir todo el código. Es una función de orden superior que toma otra función como argumento y devuelve una versión modificada de ella.
El decorador modifica el objeto original, que se le pasa como argumento, y devuelve una versión actualizada que está vinculada al nombre utilizado en la definición. Los decoradores se utilizan ampliamente en la comunidad de Python y son una característica clave del lenguaje que permite a los desarrolladores escribir un código más conciso y elegante.
Son particularmente útiles cuando se trabaja con bases de código grandes, ya que permiten a los desarrolladores realizar cambios en el comportamiento de una función sin tener que modificar su implementación. Además, los decoradores se pueden utilizar para agregar nueva funcionalidad a una función, como registro, almacenamiento en caché o autenticación, sin tener que modificar su código fuente.
En general, los decoradores son una herramienta poderosa que puede ayudar a los desarrolladores a escribir un código más eficiente y mantenible en Python.
Ejemplo:
Aquí tienes un ejemplo básico de un decorador en Python:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Cuando ejecutas este código, verás:hen you run this code, you'll see:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
En el ejemplo anterior, @my_decorator
es un decorador. Las funciones que toman otras funciones como argumentos también se llaman funciones de orden superior. En este caso, my_decorator
es una función de orden superior.
El símbolo @
es solo azúcar sintáctica que nos permite aplicar fácilmente un decorador a una función. La línea @my_decorator
es equivalente a say_hello = my_decorator(say_hello)
.
Esto puede ser mucho para asimilar si eres nuevo en los decoradores. No te preocupes. Los decoradores son una herramienta poderosa en Python, pero pueden ser un poco difíciles de entender al principio. Simplemente tómate tu tiempo con este concepto, juega un poco con algunos ejemplos y le tomarás la mano.
El concepto de decoradores abre todo un nuevo mundo de posibilidades en Python. Se pueden utilizar para registro, aplicación de control de acceso y autenticación, limitación de velocidad, almacenamiento en caché y mucho más.
Los fabricantes de decoradores se pueden utilizar cuando deseas usar un decorador, pero necesitas proporcionarle argumentos. Un fabricante de decoradores es una función que devuelve un decorador. Así es cómo puedes crear uno:
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello {name}")
greet("World")
En este ejemplo, repeat(num_times=3)
devuelve un decorador que repetirá la función decorada tres veces. Esto se llama un fabricante de decoradores.
Cuando ejecutas este código, verás:
Hello World
Hello World
Hello World
Como puedes ver, la función greet fue llamada tres veces.
Este es un uso más avanzado de los decoradores, pero una vez que los entiendes, pueden ser increíblemente poderosos y ayudar a que tu código sea más legible y mantenible. La capacidad de modificar el comportamiento de una función de una manera tan limpia y legible es una de las cosas que hace que Python sea un gran lenguaje para trabajar.