2.23. Koristelijat#
Koristelija on syntaksin pala, joka kietoo funktion (tai metodin) toiseen funktioon. Kääre voi lisätä käyttäytymistä ennen alkuperäistä kutsua ja sen jälkeen, korvata paluuarvon tai liittää metatietoja. Muoto on:
@wrapper
def f():
...
@wrapper-rivi vastaa lauseketta f = wrapper(f) – funktio f rakennetaan normaalisti, sitten luovutetaan funktiolle wrapper, ja tulos sidotaan uudelleen nimeen f.
Koristelija ottaa funktion sisään ja palauttaa uuden funktion.#
2.23.1. Sisäänrakennetut metodikoristelijat#
Muutama koristelija tulee Pythonin mukana ja niitä käytetään luokkarunkojen sisällä.
2.23.1.1. @property#
Muuttaa metodin lasketuksi attribuutiksi. Kutsuja käyttää sitä kuin se olisi tavallinen attribuutti (ei sulkeita), mutta metodi suoritetaan jokaisella lukukerralla:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return 3.14159 * self.radius * self.radius
c = Circle(5)
print(c.area) # 78.53975 -- no parentheses
Käytä sitä, kun attribuutti, joka näyttää yksinkertaiselta, tarvitsee pienen laskennan taustalleen. Jos työ on kallista, suosi tavallista metodia – kutsujat eivät odota attribuuttilukujen olevan hitaita.
2.23.1.2. @classmethod#
Määrittelee metodin, joka saa luokan ensimmäisenä argumenttinaan instanssin sijaan. Ensimmäinen parametri nimetään sopimuksen mukaan nimellä cls:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def origin(cls):
return cls(0, 0)
p = Point.origin()
Luokkametodit ovat vakiotapa tarjota vaihtoehtoisia konstruktoreita – tehdasfunktioita, jotka palauttavat ei-oletustavalla rakennetun instanssin.
2.23.1.3. @staticmethod#
Määrittelee metodin, joka ei saa instanssia eikä luokkaa – se on vain tavallinen funktio, joka elää luokan nimiavaruudessa järjestelysyistä:
class Temperature:
@staticmethod
def c_to_f(c):
return c * 9 / 5 + 32
Temperature.c_to_f(100) # 212.0
Käytä sitä säästeliäästi; jos funktiolla ei todella ole mitään tekemistä luokan tilan kanssa, tavallinen moduulitason funktio on yleensä siistimpi.
2.23.2. Mukautetun koristelijan kirjoittaminen#
Koristelija on funktio, joka ottaa funktion ja palauttaa funktion. Vähimmäismuoto:
def log_calls(func):
def wrapper(*args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
return wrapper
@log_calls
def add(a, b):
return a + b
add(2, 3)
Tuloste:
calling add
wrapper sulkeutuu func-funktion ympärille ja välittää kaiken sille. *args / **kwargs antaa sen toimia minkä tahansa funktion kanssa, ei vain kaksiargumenttisten. Tämä malli on perusta monimutkaisemmille koristelijoille (ajanotto, välimuistitus, uudelleenyritys epäonnistuessa), mutta ydin on aina sama: ota funktio sisään, palauta funktio ulos.