În lumea vastă a programării Python, există un set de caracteristici care trec adesea neobservate de începători, dar au o importanță semnificativă în ecosistemul limbajului.
Metodele magice sunt un set de metode prealabiledefinite în Python care oferă caracteristici sintactice speciale. Sunt ușor de recunoscut după liniuțele lor duble la început și la sfârșit, cum ar fi __init__, __call__, __len__
… etc.
Metodele magice permit obiectelor personalizate să se comporte similar cu tipurile Python încorporate.
În acest articol, ne vom concentra asupra funcțiilor puternice dunder. Vom explora scopul lor și vom discuta despre utilizarea lor.
Indiferent dacă sunteți un novice în Python sau un programator cu experiență, acest articol își propune să vă ofere o înțelegere cuprinzătoare a funcțiilor Dunder, făcând experiența dvs. de codare Python mai eficientă și plăcută.
Amintiți-vă, magia lui Python nu constă numai în simplitatea și versatilitatea sa, ci și în caracteristicile sale puternice, cum ar fi funcțiile Dunder.
Poate cea mai elementară funcție dunder dintre toate. Aceasta este metoda magică pe care Python o apelează automat ori de câte ori creăm (sau, după cum sugerează și numele, inițializam) un obiect nou.__init__
clasa pizza:
def __init__(self, size, toppings):
self.size = dimensiune
self.toppings = toppings
# Acum să creăm o pizza
my_pizza = Pizza('mare', ['pepperoni', 'ciuperci'])
print(my_pizza.size) # Acesta va imprima: mare
print(my_pizza.toppings) # Acesta va imprima: ['pepperoni', 'ciuperci']
În acest exemplu, este creată o clasă numită Pizza. Am configurat funcția noastră __init__ pentru a include parametrii pe care să îi specificam la momentul inițializării și să-i setăm ca proprietăți pentru obiectul nostru personalizat.
Aici, este folosit pentru a reprezenta instanța clasei. Deci, când scriem self.size = dimensiune, spunem: „Hei, acest obiect pizza are o dimensiune de atribut size
, și vreau să aibă orice dimensiune am furnizat-o când am creat obiectul”.
Aceasta este metoda magică a lui Python care ne permite defifinalizați o descriere pentru articolul nostru personalizat.
Când imprimați un obiect sau îl convertiți într-un șir folosind str()
, Python verifica dacă ai defiAm venit cu o metodă __str__
pentru clasa obiectului respectiv.
Dacă da, utilizați acea metodă pentru a converti obiectul într-un șir.
Putem extinde exemplul nostru de Pizza pentru a include o funcție __str__
după cum urmează:
clasa Pizza: def __init__(self, size, toppings): self.size = dimensiune self.toppings = toppings def __str__(self): return f"O pizza {self.size} cu {', '.join(self.toppings) )}" my_pizza = Pizza('large', ['pepperoni', 'mushrooms']) print(my_pizza) # Se va imprima: O pizza mare cu pepperoni, ciuperci
__repr__
Funcția __str__ este mai mult un mod informal de a descrie proprietățile unui obiect. Pe de altă parte, __repr__ este folosit pentru a oferi o descriere mai formală, detaliată și lipsită de ambiguitate a obiectului personalizat.
Dacă suni repr()
pe un obiect sau doar introduceți numele obiectului în consolă, Python va căuta o metodă __repr__
.
Se __str__
nici unul definite, va folosi Python __repr__
ca rezervă atunci când încercați să imprimați obiectul sau să îl convertiți într-un șir. Deci este adesea o idee bună defitermina cel putin __repr__
, chiar dacă nu o faci defiiese __str__
.
Iată cum am putea defifinalizarea __repr__
pentru exemplul nostru de pizza:
clasa pizza:
def __init__(self, size, toppings):
self.size = dimensiune
self.toppings = toppings
def __repr__(self):
returnează f"Pizza('{self.size}', {self.toppings})"
my_pizza = Pizza('mare', ['pepperoni', 'ciuperci'])
print(repr(my_pizza)) # Acesta va imprima: Pizza('mari', ['pepperoni', 'ciuperci'])
__repr__
vă oferă un șir pe care îl puteți rula ca o comandă Python pentru a recrea obiectul pizza, în timp ce __str__
vă oferă o descriere mai umană. Sper să te ajute să mesteci puțin mai bine aceste metode dunder!
În Python, știm cu toții că este posibil să adăugați numere folosind operatorul +
, Cum 3 + 5
.
Dar dacă vrem să adăugăm instanțe ale unui obiect personalizat?
Funcția dunder __add__
ne permite să facem tocmai asta. Ne oferă capacitatea de a defitermina comportamentul operatorului +
pe articolele noastre personalizate.
În interesul coerenței, să presupunem că vrem defitermina comportamentul de +
pe exemplul nostru de pizza. Să presupunem că de fiecare dată când adăugăm două sau mai multe pizza împreună, se va combina automat toate toppingurile. Iată cum ar putea arăta:
clasa pizza:
def __init__(self, size, toppings):
self.size = dimensiune
self.toppings = toppings
def __add__(self, other):
dacă nu esteinstanță (altele, Pizza):
raise TypeError(„Puteți adăuga doar o altă pizza!”)
noi_toppings = self.toppings + other.toppings
returnează pizza(self.size, new_toppings)
# Să creăm două pizza
pizza1 = Pizza('mare', ['pepperoni', 'ciuperci'])
pizza2 = Pizza('mare', ['măsline', 'ananas'])
# Și acum să le „adăugăm”.
pizza_combinată = pizza1 + pizza2
print(combined_pizza.toppings) # Acesta va imprima: ['pepperoni', 'ciuperci', 'masline', 'ananas']
Similar cu dunder __add__
, putem de asemenea defiterminați alte funcții aritmetice precum __sub__
(prin scădere folosind operatorul -
) Și __mul__
(pentru multiplicare folosind operatorul *
).
Această metodă dunder ne permite defitermina ce functia len()
trebuie returnat pentru articolele noastre personalizate.
Python folosește len()
pentru a obține lungimea sau dimensiunea unei structuri de date, cum ar fi o listă sau șir.
În contextul exemplului nostru, am putea spune că „lungimea” unei pizza este numărul de toppinguri pe care le are. Iată cum l-am putea implementa:
clasa pizza:
def __init__(self, size, toppings):
self.size = dimensiune
self.toppings = toppings
def __len__(self):
return len(self.toppings)
# Să creăm o pizza
my_pizza = Pizza('mari', ['pepperoni', 'ciuperci', 'masline'])
print(len(my_pizza)) # Acesta va imprima: 3
În metoda __len__, returnăm doar lungimea listei toppings
. Acum, len(my_pizza)
ne va spune câte toppinguri sunt pe el my_pizza
.
Această metodă dunder permite obiectelor să fie iterabile, adică poate fi folosită într-o buclă for.
Pentru a face acest lucru, trebuie și noi defiterminați funcția __next__
, Acesta este folosit pentru defiterminați comportamentul care ar trebui să returneze următoarea valoare din iterație. De asemenea, ar trebui să semnaleze iterabilul în cazul în care nu mai există elemente în secvență. În mod obișnuit, obținem acest lucru prin aruncarea unei excepții StopIteration
.
Pentru exemplul nostru de pizza, să presupunem că vrem să repetăm toppingurile. Am putea face clasa noastră de pizza iterabilă definendo o metodă __iter__
:
clasa pizza:
def __init__(self, size, toppings):
self.size = dimensiune
self.toppings = toppings
def __iter__(self):
sine.n = 0
întoarce-te
def __next__(self):
if self.n < len(self.toppings):
rezultat = self.toppings[self.n]
sine.n += 1
returnează rezultatul
altceva:
ridicați StopIteration
# Să creăm o pizza
my_pizza = Pizza('mari', ['pepperoni', 'ciuperci', 'masline'])
# Și acum să repetăm peste el
pentru topping in my_pizza:
imprimare (topping)
În acest caz, apelurile în buclă for __iter__
, care inițializează un numărător (self.n)
și returnează obiectul pizza în sine (self)
.
Apoi, apelurile în buclă for __next__
pentru a obține fiecare topping pe rând.
Când __next__
a returnat toate condimentele, StopIteration
se aruncă o excepție și bucla for acum știe că nu mai există toppinguri și astfel va anula procesul de iterație.
Ercole Palmeri
Luni trecută, Financial Times a anunțat un acord cu OpenAI. FT își licențiază jurnalismul de clasă mondială...
Milioane de oameni plătesc pentru serviciile de streaming, plătind taxe lunare de abonament. Este o părere comună că tu...
Coveware de la Veeam va continua să ofere servicii de răspuns la incidente de extorcare cibernetică. Coveware va oferi capacități criminalistice și de remediere...
Întreținerea predictivă revoluționează sectorul petrolului și gazelor, cu o abordare inovatoare și proactivă a managementului uzinelor...