Mi az a Functools a Pythonban? Bevezetés a Functions of Functools modulba példákkal.

A Python functools modulja egy szabványos könyvtári modul, amely magasabb rendű függvényeket és műveleteket biztosít hívható objektumokon (függvényeken, metódusokon és osztályokon). Eszközöket kínál a funkciókkal és funkciószerű objektumokkal, például dekorátorokkal, részleges funkcióalkalmazásokkal és funkciókompozíciókkal való munkához.

Történelem

A functools modul a Python 2.5 óta a Python szabványkönyvtár része. Azért vezették be, hogy további magasabb szintű funkciókat és eszközöket biztosítson a függvényekkel és hívható objektumokkal való munkavégzéshez.

Íme egy rövid idővonal a functools modul történetéről:

Python 2.5: A Functools modult a Python 2.5-ben vezették be a szabványos könyvtár részeként. Olyan funkciókat tartalmazott, mint a részleges, wraps és update_wrapper.

Python 3.2: A Python 3.2-ben a functools modul az lru_cache dekorátorral bővült. Ez a dekorátor bevezette a memorizálási képességeket, amelyek lehetővé teszik a funkciók eredményeinek hatékony gyorsítótárazását.

Python 3.3: A Python 3.3 kiadásával a cmp_to_key függvény hozzáadásra került a functools modulhoz. Módot biztosított arra, hogy egy régi stílusú összehasonlító függvényt olyan kulcsfüggvénnyel alakítsunk át, amely kompatibilis különféle eszközökkel, mint például a sorted(), a min() és a max().

Python 3.4: A Python 3.4 bevezette a singledispatch dekorátort a functools modulban. Lehetővé tette a fejlesztők számára, hogy egyszeri küldésű általános függvényeket definiáljanak, lehetővé téve a funkció túlterhelését az első argumentum típusa alapján.

Python 3.8: A Python 3.8-ban a functools modul megkapta a cached_property dekorátort. Egy osztály metódusát gyorsítótárazással rendelkező tulajdonsággá alakította át, biztosítva, hogy a számított érték csak egyszer kerüljön kiszámításra.

Python-függvények és -módszerek listája

Itt található a Python functools moduljában elérhető függvények és osztályok listája:

részleges(func, *args, **keywords)

Egy új részleges objektumot ad vissza, amely meghívásakor úgy viselkedik, mint a func meghívása az args és a kulcsszóargumentumok kulcsszavakkal.

Fedezzük fel a részleges osztály erejét! Segítségével részobjektumokat hozhat létre, lehetővé téve egy függvény részleges alkalmazását. Ha meg akarjuk érteni a nagyszerűségét, merüljünk el egy példában.

Képzelje el, hogy van egy függvénye több argumentummal. Mostantól előfordulhatnak olyan helyzetek, amikor csak néhány argumentumot szeretne módosítani, míg másokat állandónak kell tartania a függvény minden meghívásakor. Lépjen be a Python részleges osztályába, praktikus társunkba! Lehetővé teszi tetszőleges számú argumentum rögzítését anélkül, hogy külön függvényt kellene létrehozni.

Ez így működik: a részleges osztály segítségével „előre kitöltheti” a függvény bizonyos argumentumait, a többit nyitva hagyva későbbre. Így létrehozhat egy új függvényt, amely úgy viselkedik, mintha néhány argumentum már megadva lett volna. Olyan ez, mintha elkészítenéd a receptet néhány már kimért hozzávalóból, és csak akkor kell hozzáadnod a maradékot, ha készen állsz a főzésre!

A részleges osztály rugalmasságot biztosít, és szükségtelenné teszi további funkciók létrehozását a részleges alkalmazás érdekében. Olyan, mintha egy szupererővel rendelkeznél, amely leegyszerűsíti a kódodat és kifejezőbbé teszi. Tehát ölelje fel a részleges osztályt, és tárja fel a Python részleges funkcióinak alkalmazásában rejlő valódi lehetőségeket!

Példa:

from functools import partial

def messenger(type, message):
    print(f'( {type} ) : {message}')

messenger('TEXT', 'hello')
messenger('TEXT', 'world')
messenger('TEXT', 'hello world')

partialmethod(func, *args, **keywords)

Egy új parciális metódus leírót ad vissza, amely úgy viselkedik, mint a részleges, kivéve, hogy metódusfüggvényekkel való használatra tervezték.

Fedezzük fel a lenyűgöző partialmethod() függvényt! Partialmethod-leírókat ad vissza, amelyek hasonlóak a partial()-hoz, de kifejezetten metódusokhoz készültek. Más szóval, akkor ragyog, ha új módszerek meghatározásáról van szó, nem pedig közvetlenül hívhatóvá.

Ahhoz, hogy megértsük, hogyan működik, először nézzük meg a szintaxisát. Ezután a Python hivatalos dokumentációjából vett példát szemléltetjük annak használatának illusztrálására.

Most pedig térjünk az izgalmas részhez – a példához! A Python hivatalos dokumentációja nagyszerűen szemlélteti a részleges módszert működés közben. Bemutatja, hogyan használhatja ezt a funkciót előre meghatározott argumentumokkal rendelkező metódusok létrehozásához. Olyan ez, mint egy parancsikon speciális módszerek létrehozásához, amelyek öröklik és kiterjesztik a meglévő funkcionalitást.

A partialmethod segítségével javíthatja osztályai képességeit azáltal, hogy testreszabott metódusokat határoz meg, amelyek meghatározott viselkedést foglalnak magukba. Rugalmasságot és modularitást ad a kódhoz. Tehát merüljünk el a példában, és lássuk a részleges módszer erejét működés közben!

from functools import partialmethod


class Cell(object):
    def __init__(self):
        self._alive = False

    @property
    def alive(self):
        return self._alive

    def set_state(self, state):
        self._alive = bool(state)

    set_alive = partialmethod(set_state, True)
    set_dead = partialmethod(set_state, False)


aCell = Cell()
aCell.set_alive()
print(aCell.alive)

wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)

Ez egy kényelmi függvény az update_wrapper() függvény dekorátorként történő meghívásához, amikor egy burkoló függvényt definiálunk. Vegyünk egy példát,

def my_decorator(func):
def wrapper(*args, **kwargs):
    """
    Wrapper Docstring
    """
    return func(*args, **kwargs)
return wrapper

@my_decorator
def original_func():
    """
    Original Function Doctstring
    """
    return "Something"

print(original_func())
print(original_func.__name__)
print(original_func.__doc__)

Ha definiál egy wrapper függvényt, a wraps() egy fantasztikus funkciódekorátorként jön segítségül. Beveszi azt a funkciót, amelyet a csomagolóanyaga becsomagol, és varázslatosan működik!

Mit csinál a wraps()? Nos, zökkenőmentesen megváltoztatja a burkoló funkció jellemzőit, hogy azok megfeleljenek a burkolt funkció jellemzőinek. Ez olyan, mintha átalakítaná a csomagolását, hogy pontosan úgy nézzen ki, mint az eredeti funkció! De ez még nem minden – a wraps() megteszi az extra mérföldet azzal, hogy biztosítja, hogy a metaadatok, például az attribútumok és a dokumentumkarakterláncok a wrapper függvényhez tartoznak.

Ez miért fontos? A wraps() nélkül olyan hibás programokat kaphat, amelyek nem tükrözik a függvény valódi metaadatait. De a wraps() segítségével biztos lehet benne, hogy a wrapper függvény megőrzi és visszaadja a megfelelő metaadatokat, ahogy annak lennie kell.

lru_cache(maxsize=128, typed=False)

Dekorátor, amely egy funkciót egy memoizáló hívással burkol, amely a legutóbbi hívások maximális méretét menti el. Olyan ez, mint egy titkos memóriabank, amely felgyorsíthatja a funkció végrehajtását. Hogyan működik? Nos, a Memoization nevű okos technikát használja, amely a gyorsítótárazásról szól.

Képzelje el ezt: az lru_cache() esetén a függvénynek nem kell többször futnia ugyanazon bemenetek esetén. Ehelyett a függvény kimenete az első meghívásakor a memóriába kerül, és amikor legközelebb szükség lesz erre az eredményre, egy pillanat alatt visszakereshető! Olyan ez, mint egy parancsikon a szükségtelen számítások elkerülésére.

És mit jelent az LRU gyorsítótár? A legfrissebben használt gyorsítótár rövidítése. Alapvetően, ha beállítja a gyorsítótár maximális méretét, és az eléri ezt a korlátot, akkor a legutóbb használt bejegyzés törlődik. Ez olyan, mintha helyet adna az új dolgoknak, miközben biztosítja, hogy a legutóbb használt eredmények könnyen elérhetőek legyenek.

Tehát az lru_cache() használatával optimalizálhatja kódját, felgyorsíthatja a függvények végrehajtását, és értékes időt takaríthat meg. Mintha egy varázslatos gyorsítótáras dzsinn állna a szolgálatában!”

cmp_to_key(cmp): A régi stílusú összehasonlító függvény átalakítása kulcsfüggvénnyel.

reduce(függvény, iterálható[, inicializáló])

Alkalmazzon két argumentum függvényét kumulatívan az iterálható elemeire balról jobbra, hogy az iterálható egyetlen értékre csökkenjen. A Python redukciós () függvénye funkcionális számítást végez úgy, hogy egy függvényt és egy iterálható elemet (pl. sor, lista, szótár stb.) vesz be bemenetként, és visszaadja az eredményt a számítás után, azaz a függvény adott iterálására való alkalmazásának folyamata után. . A python-ban a redukció() függvény a functools modulban van definiálva, és csak egyetlen értéket ad vissza kimenetként, amely az egész iteráció eredménye, amely csak egyetlen egész számra, logikai értékre vagy karakterláncra redukálódik.

egyszeri feladás (alapértelmezett)

Egy függvény átalakítása egyszeri küldés általános függvényévé. Ez a dekorátor olyan, mint egy varázspálca, amely bármilyen normál funkciót szuperrugalmas, egyszeri kiküldés funkcióvá képes átalakítani. Az mit jelent? Nos, lehetővé teszi a Python funkcióinak könnyű túlterhelését, így a kód még sokoldalúbbá válik!

Képzelje el ezt: a singledispatch() segítségével létrehozhat egy függvény különböző verzióit, amelyek a bemenet típusától függően kerülnek meghívásra. Olyan, mintha egy kaméleon funkciója lenne, amely alkalmazkodik a különböző helyzetekhez! És képzeld csak? Ezt a fantasztikus funkciót a Python 3.4-ben vezették be, tehát meglehetősen friss és izgalmas!

Hogy segítsen megérteni a singledispatch() nagyszerűségét, merüljünk el egy példában. Kapcsold be, és készülj fel egy kis kódolási mókára!

from functools import singledispatch

@singledispatch
def add(firstEle, secondEle):
    if type(firstEle) is not type(secondEle):
        return "Unsupported type"
    return firstEle + secondEle

@add.register(int)
def _(a, b):
    return a + b

print(add(2, 4))
print(add(2, '4'))

A példában először két egész argumentumot adunk át az add függvénynek, és íme! A várt eredményt a két elem hozzáadása után kapjuk. A dolgok azonban érdekessé válnak, ha két különböző típusú argumentumot adunk át, például egy karakterláncot és egy egész számot. Ebben az esetben TypeError-ral találkozunk, mert az „int” és az „str” hozzáadásának művelete nem támogatott.

A singledispatch dekorátor lehetővé teszi, hogy különböző argumentumtípusokat kezeljünk a függvény különböző verzióival, így a kódunk rugalmasabb és robusztusabb. Ez olyan, mintha egy intelligens asszisztens lenne, amely a bemenetek típusa alapján pontosan tudja, melyik funkciót kell meghívni. nem menő?

cached_property(func): Egy osztály metódusának átalakítása olyan tulajdonsággá, amelynek értéke gyorsítótárban van.

total_ordering(cls): Adott egy osztály, amely egy vagy több gazdag összehasonlító rendezési módszert határoz meg, ez az osztálydekorátor automatikusan kitölti a hiányzó rendezési módszereket.

update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): Frissítse a burkoló függvényt vagy metódust, hogy úgy nézzen ki, mint a burkolt függvény. Az opcionális argumentumok használhatók a generált burkoló módosítására.

cmp_to_key(cmp): A régi stílusú összehasonlító függvény átalakítása kulcsfüggvénnyel. Olyan eszközökkel használható, amelyek elfogadják a kulcsfüggvényeket (például sorted(), min() és max()).

total_ordering: Adott egy osztály, amely egy vagy több gazdag összehasonlító rendezési módszert határoz meg, ez az osztálydekorátor automatikusan kitölti a hiányzó rendezési metódusokat (__lt__, __le__, __gt__ vagy __ge__) a többi gazdag összehasonlítási módszerrel (__eq__, __ne__, __lt__ vagy __gt__).

Előnyök

Hatékony gyorsítótárazás: A functools modul hatékony gyorsítótárazási szolgáltatásokat kínál, mint például az lru_cache(), a cache() és a cached_property(). Ezek a funkciók lehetővé teszik a legutóbb használt funkcióeredmények tárolását és lekérését, így a memográfia révén optimalizálja a teljesítményt. Az olyan opciókkal, mint a typed=True paraméter, testreszabhatja a gyorsítótárazási viselkedést argumentumtípusok alapján, javítva ezzel a pontosságot.

Funkciótúlterhelés: Ellentétben azzal a közhiedelemmel, hogy a funkciók túlterhelése a Pythonban lehetetlen, a functools modul olyan eszközöket biztosít, mint a singledispatch() és a singledispatchmethod() ennek eléréséhez. E technikák kihasználásával több küldési algoritmust is megvalósíthat, és futás közben dinamikusan megkülönböztetheti a típusokat, ami rugalmasabb és kifejezőbb kódolást tesz lehetővé.

Egyszerű összehasonlítás és rendezés: Az összehasonlító operátorok (lt(), gt(), eq() stb.) alkalmazása egy osztályhoz nehézkes lehet. A functools azonban a @total_ordering dekorátorral segít. Csak az eq() és egy másik összehasonlítási módszer definiálásával a dekoratőr automatikusan generálja a fennmaradó összehasonlítási módszereket, leegyszerűsítve a folyamatot és biztosítva a következetes viselkedést.

Aszinkron műveletek támogatása: Ha olyan külső könyvtárakkal vagy keretrendszerekkel dolgozik, amelyek további argumentumokkal rendelkező visszahívási függvényeket igényelnek, a functools praktikus eszközzé válik. Ha egy függvény argumentumait részlegesen lefagyasztja, új objektumot hozhat létre egyszerűsített függvénnyel, ami megkönnyíti az aszinkron műveletek és eseményfigyelők kezelését.

Dekorátor fejlesztése: A functools modul @wraps-t biztosít, ami felbecsülhetetlen a robusztusabb dekorátorok készítéséhez. A fontos metaadatok, például a függvénynév, a docstring és a modul megőrzésével a @wraps biztosítja, hogy a díszített függvény megőrizze eredeti identitását, ami tisztább és karbantarthatóbb kódot eredményez.

— — —

Miért tagadta meg a lakberendező a bulin való részvételt?

Mert nem akart belemerülni a sok mókába!

🙂🙂🙂