No vasto mundo da programación en Python, hai un conxunto de características que moitas veces pasan desapercibidas para os principiantes, aínda que teñen unha importancia significativa no ecosistema da linguaxe.
Os métodos máxicos son un conxunto de métodos previosdefien Python que proporcionan unha funcionalidade sintáctica especial. Recoñécense facilmente polos seus dobres guións ao principio e ao final, como __init__, __call__, __len__
… etc.
Os métodos máxicos permiten que os obxectos personalizados se comporten de xeito similar aos tipos de Python incorporados.
Neste artigo, centrarémonos nas poderosas funcións dunder. Exploraremos o seu propósito e discutiremos o seu uso.
Tanto se es un novato en Python como un programador experimentado, este artigo ten como obxectivo proporcionarche unha comprensión completa das funcións de Dunder, facendo que a túa experiencia de codificación en Python sexa máis eficiente e agradable.
Lembra que a maxia de Python non reside só na súa sinxeleza e versatilidade, senón tamén nas súas poderosas funcións como as funcións de Dunder.
Quizais a función dunder máis básica de todas. Este é o método máxico que Python chama automaticamente sempre que creamos (ou como o nome indica, inicializamos) un novo obxecto.__init__
clase de pizza:
def __init__(self, size, toppings):
self.size = tamaño
self.toppings = coberturas
# Agora imos crear unha pizza
my_pizza = Pizza('grande', ['pepperoni', 'cogomelos'])
print(my_pizza.size) # Isto imprimirá: grande
print(my_pizza.toppings) # Isto imprimirá: ['pepperoni', 'mushrooms']
Neste exemplo, créase unha clase chamada Pizza. Configuramos a nosa función __init__ para incluír parámetros para especificar no momento da inicialización e definimos como propiedades para o noso obxecto personalizado.
Aquí, úsase para representar a instancia da clase. Entón, cando escribimos self.size = size, estamos dicindo: "Oe, este obxecto de pizza ten un tamaño de atributo size
, e quero que teña o tamaño que proporcionei cando creei o obxecto".
Este é o método máxico de Python que nos permite defidescrición do noso artigo personalizado.
Cando imprimes un obxecto ou o convertes nunha cadea usando str()
, Python comproba se tes defiterminou un método __str__
para a clase dese obxecto.
Se é así, use ese método para converter o obxecto nunha cadea.
Podemos ampliar o noso exemplo de Pizza para incluír unha función __str__
do seguinte xeito:
class Pizza: def __init__(self, size, toppings): self.size = size self.toppings = toppings def __str__(self): return f"Una pizza {self.size} con {', '.join(self.toppings) )}" my_pizza = Pizza('grande', ['pepperoni', 'mushrooms']) print(my_pizza) # This will print: A large pizza with pepperoni, mushrooms
__repr__
A función __str__ é unha forma máis informal de describir as propiedades dun obxecto. Por outra banda, __repr__ úsase para proporcionar unha descrición máis formal, detallada e sen ambigüidades do obxecto personalizado.
Se chamas repr()
nun obxecto ou simplemente escribe o nome do obxecto na consola, Python buscará un método __repr__
.
Se __str__
Non é defiNoite, Python usará __repr__
como copia de seguridade ao intentar imprimir o obxecto ou convertelo nunha cadea. Entón, moitas veces é unha boa idea defirematar polo menos __repr__
, aínda que non o fagas defiremata __str__
.
Así é como puidemos defirematar __repr__
para o noso exemplo de pizza:
clase de pizza:
def __init__(self, size, toppings):
self.size = tamaño
self.toppings = coberturas
def __repr__(self):
devolver f"Pizza('{self.size}', {self.toppings})"
my_pizza = Pizza('grande', ['pepperoni', 'cogomelos'])
print(repr(my_pizza)) # Isto imprimirá: Pizza('grande', ['pepperoni', 'cogomelos'])
__repr__
ofrécelle unha cadea que pode executar como comando de Python para recrear o obxecto pizza, mentres que __str__
ofrécelle unha descrición máis humana. Espero que che axude a mastigar un pouco mellor estes métodos dunder.
En Python, todos sabemos que é posible engadir números usando o operador +
, como 3 + 5
.
Pero e se queremos engadir instancias dalgún obxecto personalizado?
A función dunder __add__
permítenos facer precisamente iso. Dános a oportunidade defirefinar o comportamento do operador +
nos nosos artigos personalizados.
En aras da coherencia, supoñamos que queremos definite o comportamento de +
no noso exemplo de pizza. Digamos que sempre que engadimos dúas ou máis pizzas xuntas, combinará automaticamente todas as súas coberturas. Aquí tes como pode parecer:
clase de pizza:
def __init__(self, size, toppings):
self.size = tamaño
self.toppings = coberturas
def __add__(self, other):
se non é unha instancia (outro, Pizza):
raise TypeError ("Só pode engadir outra pizza!")
novos_toppings = self.toppings + other.toppings
devolver Pizza (tamaño propio, novos_toppings)
# Creamos dúas pizzas
pizza1 = Pizza('grande', ['pepperoni', 'cogomelos'])
pizza2 = Pizza('grande', ['aceitunas', 'piña'])
# E agora imos "engadilos".
pizza_combinada = pizza1 + pizza2
print(combined_pizza.toppings) # Isto imprimirá: ['pepperoni', 'cogomelos', 'olivas', 'piña']
Do mesmo xeito que Dunder __add__
, nós tamén podemos definite outras funcións aritméticas como __sub__
(por resta usando o operador -
) E __mul__
(para multiplicar usando o operador *
).
Este método dunder permítenos defirematar cal é a función len()
debemos devolver os nosos artigos personalizados.
Usos de Python len()
para obter a lonxitude ou o tamaño dunha estrutura de datos como unha lista ou unha cadea.
No contexto do noso exemplo, poderiamos dicir que a "longitud" dunha pizza é o número de coberturas que ten. Así é como podemos implementalo:
clase de pizza:
def __init__(self, size, toppings):
self.size = tamaño
self.toppings = coberturas
def __len__(self):
return len(self.toppings)
# Creamos unha pizza
my_pizza = Pizza('grande', ['pepperoni', 'cogomelos', 'olivas'])
print(len(my_pizza)) # Isto imprimirá: 3
No método __len__ só devolvemos a lonxitude da lista toppings
. Agora, len(my_pizza)
indicaranos cantos ingredientes hai my_pizza
.
Este método dunder permite que os obxectos sexan iterables, é dicir, pódese usar nun bucle for.
Para iso, tamén debemos defirematar a función __next__
, Isto úsase para defifinaliza o comportamento que debería devolver o seguinte valor na iteración. Ademais, tamén debería sinalar ao iterable no caso de que non haxa máis elementos na secuencia. Normalmente conseguimos isto levantando unha excepción StopIteration
.
Para o noso exemplo de pizza, digamos que queremos repetir os ingredientes. Poderiamos facer que a nosa clase de pizza sexa iterable defidando un método __iter__
:
clase de pizza:
def __init__(self, size, toppings):
self.size = tamaño
self.toppings = coberturas
def __iter__(self):
propio.n = 0
volver a si mesmo
def __next__(self):
if self.n < len(self.toppings):
resultado = self.toppings[self.n]
propio.n += 1
devolver o resultado
senón:
aumentar StopIteration
# Creamos unha pizza
my_pizza = Pizza('grande', ['pepperoni', 'cogomelos', 'olivas'])
# E agora imos repetir
para cubrir a miña_pizza:
imprimir (topping)
Neste caso, as chamadas de bucle for __iter__
, que inicializa un contador (self.n)
e devolve o propio obxecto pizza (self)
.
Despois, as chamadas de bucle for __next__
para conseguir cada cobertura á súa vez.
cando __next__
devolveu todos os condimentos, StopIteration
lanza unha excepción e o bucle for agora sabe que non hai máis coberturas e, polo tanto, abortará o proceso de iteración.
Ercole Palmeri
O sector naval é unha verdadeira potencia económica mundial, que navega cara a un mercado de 150 millóns...
O pasado luns, o Financial Times anunciou un acordo con OpenAI. FT licencia o seu xornalismo de clase mundial...
Millóns de persoas pagan por servizos de streaming, pagando taxas de subscrición mensuais. É unha opinión común que vostede...
Coveware by Veeam continuará ofrecendo servizos de resposta a incidentes de extorsión cibernética. Coveware ofrecerá capacidades forenses e de remediación...