functools
— Funktioner av högre ordning och operationer på anropsbara objekt¶
Källkod: Lib/functools.py
Modulen functools
är avsedd för funktioner av högre ordning: funktioner som agerar på eller returnerar andra funktioner. I allmänhet kan alla anropsbara objekt behandlas som en funktion i den här modulen.
Modulen functools
definierar följande funktioner:
- @functools.cache(user_function)¶
Enkel lättviktig obegränsad funktionscache. Kallas ibland för ”memoize”.
Returnerar samma sak som
lru_cache(maxsize=None)
, vilket skapar ett tunt hölje runt en ordboksuppslagning för funktionsargumenten. Eftersom den aldrig behöver evakuera gamla värden är den här mindre och snabbare änlru_cache()
med en storleksbegränsning.Till exempel:
@cache def factorial(n): return n * factorial(n-1) if n else 1 >>> factorial(10) # no previously cached result, makes 11 recursive calls 3628800 >>> factorial(5) # just looks up cached value result 120 >>> factorial(12) # makes two new recursive calls, the other 10 are cached 479001600
Cachen är trådsäker så att den omslutna funktionen kan användas i flera trådar. Detta innebär att den underliggande datastrukturen förblir sammanhängande under samtidiga uppdateringar.
Det är möjligt att den inkapslade funktionen anropas mer än en gång om en annan tråd gör ett ytterligare anrop innan det första anropet har slutförts och cachats.
Tillagd i version 3.9.
- @functools.cached_property(func)¶
Omvandlar en metod i en klass till en egenskap vars värde beräknas en gång och sedan cachelagras som ett normalt attribut under instansens livstid. Liknar
property()
, med tillägg av cachelagring. Användbar för dyra beräknade egenskaper hos instanser som annars är effektivt oföränderliga.Exempel:
klass DataSet: def __init__(self, sequence_of_numbers): self._data = tuple(sequence_of_numbers) @cachad_egenskap def stdev(self): return statistik.stdev(self._data)
Mekaniken i
cached_property()
är något annorlunda än iproperty()
. En vanlig property blockerar skrivningar av attribut om inte en setter är definierad. Däremot tillåter en cached_property skrivningar.Dekoratorn cached_property körs endast vid uppslagningar och endast när ett attribut med samma namn inte existerar. När den körs skriver cached_property till attributet med samma namn. Efterföljande läsningar och skrivningar av attribut har företräde framför metoden cached_property och den fungerar som ett vanligt attribut.
Det cachade värdet kan rensas genom att attributet tas bort. Detta gör att metoden cached_property kan köras igen.
Egenskapen cached_property förhindrar inte ett möjligt tävlingsförhållande vid användning med flera trådar. Getter-funktionen kan köras mer än en gång på samma instans, där den senaste körningen ställer in det cachade värdet. Om den cachade egenskapen är idempotent eller på annat sätt inte skadlig för att köras mer än en gång på en instans, är detta bra. Om synkronisering behövs, implementera den nödvändiga låsningen i den dekorerade getter-funktionen eller runt åtkomsten till den cachade egenskapen.
Observera att denna dekorator stör funktionen hos PEP 412 nyckeldelningsordböcker. Detta innebär att instansordböcker kan ta mer utrymme än vanligt.
Den här dekoratorn kräver också att attributet
__dict__
på varje instans är en muterbar mappning. Detta innebär att den inte kommer att fungera med vissa typer, till exempel metaklasser (eftersom attributen__dict__
på typinstanser är skrivskyddade proxyer för klassens namnrymd) och de som anger__slots__
utan att inkludera__dict__
som en av de definierade slottarna (eftersom sådana klasser inte tillhandahåller ett attribut__dict__
alls).Om en mutabel mappning inte är tillgänglig eller om utrymmeseffektiv nyckeldelning önskas, kan en effekt som liknar
cached_property()
också uppnås genom att staplaproperty()
ovanpålru_cache()
. Se Hur cachar jag metodanrop? för mer information om hur detta skiljer sig fråncached_property()
.Tillagd i version 3.8.
Ändrad i version 3.12: Före Python 3.12 inkluderade
cached_property
ett odokumenterat lås för att säkerställa att getter-funktionen garanterat bara kördes en gång per instans vid flertrådig användning. Låset var dock per egenskap, inte per instans, vilket kunde resultera i oacceptabelt hög låskonflikt. I Python 3.12+ är denna låsning borttagen.
- functools.cmp_to_key(func)¶
Omvandlar en gammaldags jämförelsefunktion till en key function. Används med verktyg som accepterar nyckelfunktioner (t.ex.
sorted()
,min()
,max()
,heapq.nlargest()
,heapq.nsmallest()
,itertools.groupby()
). Denna funktion används främst som ett övergångsverktyg för program som konverteras från Python 2 som stödde användningen av jämförelsefunktioner.En jämförelsefunktion är en anropsbar funktion som tar emot två argument, jämför dem och returnerar ett negativt tal för mindre än, noll för likhet eller ett positivt tal för större än. En nyckelfunktion är en anropsbar funktion som tar emot ett argument och returnerar ett annat värde som används som sorteringsnyckel.
Exempel:
sorterad(iterabel, nyckel=cmp_till_nyckel(locale.strcoll)) # lokalmedveten sorteringsordning
För sorteringsexempel och en kort sorteringshandledning, se Sorteringstekniker.
Tillagd i version 3.2.
- @functools.lru_cache(user_function)¶
- @functools.lru_cache(maxsize=128, typed=False)
Dekorator för att omsluta en funktion med en memoizing callable som sparar upp till maxsize senaste anrop. Det kan spara tid när en dyr eller I/O-bunden funktion anropas med jämna mellanrum med samma argument.
Cachen är trådsäker så att den omslutna funktionen kan användas i flera trådar. Detta innebär att den underliggande datastrukturen förblir sammanhängande under samtidiga uppdateringar.
Det är möjligt att den inkapslade funktionen anropas mer än en gång om en annan tråd gör ett ytterligare anrop innan det första anropet har slutförts och cachats.
Eftersom en ordbok används för att cacha resultat måste positionella argument och nyckelordsargument till funktionen vara hashable.
Olika argumentmönster kan betraktas som olika anrop med olika cacheposter. Till exempel skiljer sig
f(a=1, b=2)
ochf(b=2, a=1)
åt i ordningsföljden på nyckelordets argument och kan ha två separata cacheposter.Om user_function specificeras måste den vara en callable. Detta gör att lru_cache-dekoratorn kan tillämpas direkt på en användarfunktion, och maxsize behåller sitt standardvärde på 128:
@lru_cache def count_vowels(mening): return sum(mening.count(vokal) för vokal i 'AEIOUaeiou')
Om maxsize är satt till
None
inaktiveras LRU-funktionen och cacheminnet kan växa obegränsat.Om typed är satt till true kommer funktionsargument av olika typer att cachas separat. Om typed är false kommer implementationen vanligtvis att betrakta dem som likvärdiga anrop och bara cacha ett enda resultat. (Vissa typer som str och int kan cachelagras separat även när typed är false.)
Observera att typspecificitet endast gäller funktionens omedelbara argument och inte deras innehåll. De skalära argumenten
Decimal(42))
ochFraction(42))
behandlas som distinkta anrop med distinkta resultat. Däremot behandlas tupelargumenten('answer', Decimal(42))
och('answer', Fraction(42))
som likvärdiga.Den omslutna funktionen är utrustad med en
cache_parameters()
-funktion som returnerar en nydict
som visar värdena för maxsize och typed. Detta är endast för informationsändamål. Mutation av värdena har ingen effekt.För att hjälpa till att mäta effektiviteten i cacheminnet och justera parametern maxsize har den omslutna funktionen försetts med en
cache_info()
-funktion som returnerar en named tuple med hits, misses, maxsize och currsize.Dekoratorn innehåller också en
cache_clear()
-funktion för att tömma eller inaktivera cachen.Den underliggande originalfunktionen är tillgänglig via attributet
__wrapped__
. Detta är användbart för introspektion, för att kringgå cacheminnet eller för att återpacka funktionen med ett annat cacheminne.Cachen behåller referenser till argumenten och returvärdena tills de åldras ut ur cachen eller tills cachen rensas.
Om en metod cachelagras inkluderas instansargumentet
self
i cacheminnet. Se Hur cachar jag metodanrop?En LRU-cache (least recently used) fungerar bäst när de senaste anropen är de bästa indikatorerna på kommande anrop (t.ex. de mest populära artiklarna på en nyhetsserver tenderar att ändras varje dag). Cachens storleksbegränsning säkerställer att cacheminnet inte växer obegränsat i långvariga processer, t.ex. webbservrar.
I allmänhet bör LRU-cachen endast användas när du vill återanvända tidigare beräknade värden. Följaktligen är det inte meningsfullt att cachelagra funktioner med bieffekter, funktioner som måste skapa distinkta föränderliga objekt vid varje anrop (t.ex. generatorer och asynkrona funktioner) eller orena funktioner som time() eller random().
Exempel på en LRU-cache för statiskt webbinnehåll:
@lru_cache(maxsize=32) def get_pep(num): 'Retrieve text of a Python Enhancement Proposal' resource = f'https://peps.python.org/pep-{num:04d}' try: with urllib.request.urlopen(resource) as s: return s.read() except urllib.error.HTTPError: return 'Not Found' >>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991: ... pep = get_pep(n) ... print(n, len(pep)) >>> get_pep.cache_info() CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
Exempel på effektiv beräkning av Fibonacci-tal med hjälp av en cache för att implementera en teknik för dynamisk programmering:
@lru_cache(maxsize=None) def fib(n): if n < 2: return n return fib(n-1) + fib(n-2) >>> [fib(n) for n in range(16)] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] >>> fib.cache_info() CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)
Tillagd i version 3.2.
Ändrad i version 3.3: Alternativet typed har lagts till.
Ändrad i version 3.8: Lagt till alternativet user_function.
Ändrad i version 3.9: Lagt till funktionen
cache_parameters()
- @functools.total_ordering¶
Om en klass definierar en eller flera ordningsmetoder för rik jämförelse, tillhandahåller denna klassdekorator resten. Detta förenklar arbetet med att specificera alla möjliga operationer för rik jämförelse:
Klassen måste definiera en av
__lt__()
,__le__()
,__gt__()
eller__ge__()
. Dessutom bör klassen tillhandahålla en__eq__()
-metod.Till exempel:
@total_beställning klass Student: def _is_valid_operand(self, other): return (hasattr(other, "efternamn") och hasattr(annan, "förnamn")) def __eq__(self, annan): if not self._is_valid_operand(other): return Ej implementerad return ((self.efternamn.lower(), self.förnamn.lower()) == (other.efternamn.lower()) (other.lastname.lower(), other.firstname.lower())) def __lt__(self, annan): if not self._is_valid_operand(other): return Ej implementerad return ((self.efternamn.lower(), self.förnamn.lower()) < (other.efternamn.lower(), other.förnamn.lower())))
Anteckning
Den här dekoratorn gör det enkelt att skapa välfungerande, helt ordnade typer, men det sker på bekostnad av långsammare exekvering och mer komplexa stackspår för de härledda jämförelsemetoderna. Om prestandajämförelser visar att detta är en flaskhals för en viss applikation, är det troligt att det är enkelt att öka hastigheten genom att implementera alla sex rika jämförelsemetoderna istället.
Anteckning
Denna dekorator gör inga försök att åsidosätta metoder som har deklarerats i klassen eller dess superklasser. Det betyder att om en superklass definierar en jämförelseoperator, kommer total_ordering inte att implementera den igen, även om den ursprungliga metoden är abstrakt.
Tillagd i version 3.2.
Ändrad i version 3.4: Det finns nu stöd för att returnera
NotImplemented
från den underliggande jämförelsefunktionen för okända typer.
- functools.Placeholder¶
Ett singleton-objekt som används som en sentinel för att reservera en plats för positionella argument vid anrop av
partial()
ochpartialmethod()
.Tillagd i version 3.14.
- functools.partial(func, /, *args, **keywords)¶
Returnerar ett nytt partial object som när det anropas kommer att bete sig som func anropat med de positionella argumenten args och nyckelordsargumenten keywords. Om fler argument anges vid anropet läggs de till args. Om ytterligare nyckelordsargument anges utökar och åsidosätter de keywords. Ungefär likvärdig med:
def partial(func, /, *args, **nyckelord): def newfunc(*fler_args, **fler_nyckelord): return func(*args, *mer_args, **(nyckelord | mer_nyckelord)) newfunc.func = func newfunc.args = args newfunc.nyckelord = nyckelord returnera newfunc
Funktionen
partial()
används för partiell funktionstillämpning som ”fryser” en del av en funktions argument och/eller nyckelord, vilket resulterar i ett nytt objekt med en förenklad signatur. Till exempel kanpartial()
användas för att skapa en anropsbar funktion som beter sig somint()
-funktionen där base-argumentet som standard är2
:>>> basetwo = partial(int, base=2) >>> basetwo.__doc__ = 'Convert base 2 string to an int.' >>> basetwo('10010') 18
Om
Placeholder
sentinels finns i args, kommer de att fyllas först närpartial()
anropas. Detta gör det möjligt att förfylla vilket positionsargument som helst med ett anrop tillpartial()
; utanPlaceholder
kan endast det valda antalet ledande positionsargument förfyllas.Om det finns några
Placeholder
sentineller måste alla fyllas vid anropstillfället:>>> say_to_world = partial(print, Placeholder, Placeholder, "world!") >>> say_to_world('Hello', 'dear') Hello dear world!
Anropet av
say_to_world('Hello')
ger upphov till ettTypeError
, eftersom endast ett positionellt argument anges, men det finns två platshållare som måste fyllas i.Om
partial()
tillämpas på ett befintligtpartial()
-objekt, fyllsPlaceholder
sentinels i input-objektet med nya positionsargument. En platshållare kan behållas genom att infoga en nyPlaceholder
sentinel till den plats som innehas av en tidigarePlaceholder
:>>> from functools import partial, Placeholder as _ >>> remove = partial(str.replace, _, _, '') >>> message = 'Hello, dear dear world!' >>> remove(message, ' dear') 'Hello, world!' >>> remove_dear = partial(remove, _, ' dear') >>> remove_dear(message) 'Hello, world!' >>> remove_first_dear = partial(remove_dear, _, 1) >>> remove_first_dear(message) 'Hello, dear world!'
Placeholder
kan inte skickas tillpartial()
som ett nyckelordsargument.Ändrad i version 3.14: Lagt till stöd för
Placeholder
i positionella argument.
- class functools.partialmethod(func, /, *args, **keywords)¶
Returnerar en ny
partialmethod
deskriptor som beter sig sompartial
förutom att den är utformad för att användas som en metoddefinition snarare än att vara direkt anropsbar.func måste vara en descriptor eller en callable (objekt som är både och, som vanliga funktioner, hanteras som descriptors).
När func är en deskriptor (t.ex. en vanlig Python-funktion,
classmethod()
,staticmethod()
,abstractmethod()
eller en annan instans avpartialmethod
), delegeras anrop till__get__
till den underliggande deskriptorn och ett lämpligt partialobjekt returneras som resultat.När func är en non-descriptor callable, skapas en lämplig bunden metod dynamiskt. Detta beter sig som en vanlig Python-funktion när den används som en metod: argumentet self kommer att infogas som det första positionella argumentet, till och med före de args och keywords som anges i
partialmethod
-konstruktören.Exempel:
>>> class Cell: ... 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) ... >>> c = Cell() >>> c.alive False >>> c.set_alive() >>> c.alive True
Tillagd i version 3.4.
- functools.reduce(function, iterable, /[, initial])¶
Tillämpa funktion med två argument kumulativt på objekten i iterabel, från vänster till höger, så att iterabeln reduceras till ett enda värde. Till exempel beräknar
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
((((1+2)+3)+4)+5)
. Det vänstra argumentet, x, är det ackumulerade värdet och det högra argumentet, y, är uppdateringsvärdet från iterable. Om det valfria initial finns med placeras det före iterabelns objekt i beräkningen och fungerar som standard när iterabeln är tom. Om initial inte anges och iterable bara innehåller ett objekt, returneras det första objektet.Ungefär motsvarande:
initial_missing = objekt() def reduce(function, iterable, /, initial=initial_missing): det = iter(iterabel) om initial är initial_missing: värde = nästa(det) i annat fall värde = initial för element i it: värde = funktion(värde, element) returnerar värde
Se
itertools.accumulate()
för en iterator som ger alla mellanliggande värden.Ändrad i version 3.14: initial stöds nu som ett nyckelordsargument.
- @functools.singledispatch¶
Omvandla en funktion till en single-dispatch generisk funktion.
För att definiera en generisk funktion, dekorera den med dekoratorn
@singledispatch
. När du definierar en funktion med hjälp av@singledispatch
, observera att dispatch sker på typen av det första argumentet:>>> from functools import singledispatch >>> @singledispatch ... def fun(arg, verbose=False): ... if verbose: ... print("Let me just say,", end=" ") ... print(arg)
För att lägga till överladdade implementationer till funktionen, använd
register()
-attributet för den generiska funktionen, som kan användas som en dekorator. För funktioner som är annoterade med typer kommer dekoratorn automatiskt att härleda typen av det första argumentet:>>> @fun.register ... def _(arg: int, verbose=False): ... if verbose: ... print("Strength in numbers, eh?", end=" ") ... print(arg) ... >>> @fun.register ... def _(arg: list, verbose=False): ... if verbose: ... print("Enumerate this:") ... for i, elem in enumerate(arg): ... print(i, elem)
typing.Union
kan också användas:>>> @fun.register ... def _(arg: int | float, verbose=False): ... if verbose: ... print("Strength in numbers, eh?", end=" ") ... print(arg) ... >>> from typing import Union >>> @fun.register ... def _(arg: Union[list, set], verbose=False): ... if verbose: ... print("Enumerate this:") ... for i, elem in enumerate(arg): ... print(i, elem) ...
För kod som inte använder typannoteringar kan det lämpliga typargumentet skickas explicit till själva dekoratorn:
>>> @fun.register(complex) ... def _(arg, verbose=False): ... if verbose: ... print("Better than complicated.", end=" ") ... print(arg.real, arg.imag) ...
För kod som skickar på en samlingstyp (t.ex.
list
), men som vill typmarkera objekten i samlingen (t.ex.list[int]
), bör sändningstypen skickas uttryckligen till dekoratorn själv med typmarkeringen som går in i funktionsdefinitionen:>>> @fun.register(list) ... def _(arg: list[int], verbose=False): ... if verbose: ... print("Enumerate this:") ... for i, elem in enumerate(arg): ... print(i, elem)
Anteckning
Vid körning kommer funktionen att skickas till en instans av en lista oavsett vilken typ som finns i listan, dvs.
[1,2,3]
kommer att skickas på samma sätt som["foo", "bar", "baz"]
. Annoteringen i det här exemplet är endast avsedd för statiska typkontrollanter och har ingen inverkan på körtiden.För att möjliggöra registrering av lambdas och redan existerande funktioner kan attributet
register()
också användas i en funktionell form:>>> def nothing(arg, verbose=False): ... print("Nothing.") ... >>> fun.register(type(None), nothing)
Attributet
register()
returnerar den odekorerade funktionen. Detta möjliggör stapling av dekoratorer,pickling
, och skapandet av enhetstester för varje variant oberoende av varandra:>>> @fun.register(float) ... @fun.register(Decimal) ... def fun_num(arg, verbose=False): ... if verbose: ... print("Half of your number:", end=" ") ... print(arg / 2) ... >>> fun_num is fun False
När den generiska funktionen anropas dispatchas den utifrån typen av det första argumentet:
>>> fun("Hello, world.") Hello, world. >>> fun("test.", verbose=True) Let me just say, test. >>> fun(42, verbose=True) Strength in numbers, eh? 42 >>> fun(['spam', 'spam', 'eggs', 'spam'], verbose=True) Enumerate this: 0 spam 1 spam 2 eggs 3 spam >>> fun(None) Nothing. >>> fun(1.23) 0.615
Om det inte finns någon registrerad implementation för en viss typ används dess metodupplösningsordning för att hitta en mer generisk implementation. Den ursprungliga funktionen dekorerad med
@singledispatch
är registrerad för bastypenobject
, vilket innebär att den används om ingen bättre implementation hittas.Om en implementation är registrerad för en abstrakt basklass, kommer virtuella subklasser av basklassen att skickas till denna implementation:
>>> from collections.abc import Mapping >>> @fun.register ... def _(arg: Mapping, verbose=False): ... if verbose: ... print("Keys & Values") ... for key, value in arg.items(): ... print(key, "=>", value) ... >>> fun({"a": "b"}) a => b
För att kontrollera vilken implementering den generiska funktionen kommer att välja för en viss typ, använd attributet
dispatch()
:>>> fun.dispatch(float) <function fun_num at 0x1035a2840> >>> fun.dispatch(dict) # note: default implementation <function fun at 0x103fe0000>
För att få tillgång till alla registrerade implementationer, använd det skrivskyddade attributet
registry
:>>> fun.registry.keys() dict_keys([<class 'NoneType'>, <class 'int'>, <class 'object'>, <class 'decimal.Decimal'>, <class 'list'>, <class 'float'>]) >>> fun.registry[float] <function fun_num at 0x1035a2840> >>> fun.registry[object] <function fun at 0x103fe0000>
Tillagd i version 3.4.
Ändrad i version 3.7: Attributet
register()
stöder nu användning av typannoteringar.Ändrad i version 3.11: Attributet
register()
stöder nutyping.Union
som typannotering.
- class functools.singledispatchmethod(func)¶
Omvandla en metod till en single-dispatch generic function.
För att definiera en generisk metod, dekorera den med dekoratorn
@singledispatchmethod
. När du definierar en funktion med hjälp av@singledispatchmethod
, observera att dispatch sker på typen av det första argumentet som inte är self eller cls:klass Negator: @singledispatchmetod def neg(self, arg): raise NotImplementedError("Kan inte negera a") @neg.register def _(self, arg: int): return -arg @neg.register def _(self, arg: bool): returnerar inte arg
@singledispatchmethod
stöder nestning med andra dekoratorer som@classmethod
. Notera att för att tillåtadispatcher.register
måstesingledispatchmethod
vara den yttersta dekoratorn. Här ärNegator
klassen medneg
metoderna bundna till klassen, snarare än en instans av klassen:klass Negator: @singledispatchmetod @klassmetod def neg(cls, arg): raise NotImplementedError("Kan inte negera a") @neg.register @klassmetod def _(cls, arg: int): returnerar -arg @neg.register @klassmetod def _(cls, arg: bool): returnerar inte arg
Samma mönster kan användas för andra liknande dekoratorer:
@staticmethod
,@abstractmethod
, och andra.Tillagd i version 3.8.
- functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)¶
Uppdaterar en omslagsfunktion så att den ser ut som den omhöljda funktionen. De valfria argumenten är tupler som anger vilka attribut i originalfunktionen som tilldelas direkt till de matchande attributen i omslagsfunktionen och vilka attribut i omslagsfunktionen som uppdateras med motsvarande attribut från originalfunktionen. Standardvärdena för dessa argument är modulnivåkonstanterna
WRAPPER_ASSIGNMENTS
(som tilldelar omslagsfunktionens__module__
,__name__
,__qualname__
,__annotations__
,__type_params__
, och__doc__
, dokumentationssträngen) ochWRAPPER_UPDATES
(som uppdaterar omslagsfunktionens__dict__
, dvs. instansordboken).För att tillåta åtkomst till originalfunktionen för introspektion och andra ändamål (t.ex. kringgå en cachningsdekorator som
lru_cache()
), lägger denna funktion automatiskt till ett__wrapped__
-attribut till omslaget som refererar till den funktion som omslaget avser.Den här funktionen är främst avsedd att användas i decorator-funktioner som omsluter den dekorerade funktionen och returnerar omslaget. Om omslutningsfunktionen inte uppdateras kommer metadata för den returnerade funktionen att återspegla omslutningsdefinitionen snarare än den ursprungliga funktionsdefinitionen, vilket vanligtvis inte är till någon större hjälp.
update_wrapper()
kan användas med andra anropbara objekt än funktioner. Alla attribut som namnges i assigned eller updated som saknas från objektet som omsluts ignoreras (dvs. denna funktion kommer inte att försöka ställa in dem på omslutningsfunktionen).AttributeError
utlöses fortfarande om omslutningsfunktionen själv saknar några attribut som namnges i updated.Ändrad i version 3.2: Attributet
__wrapped__
läggs nu till automatiskt. Attributet__annotations__
kopieras nu som standard. Saknade attribut utlöser inte längre ettAttributeError
.Ändrad i version 3.4: Attributet
__wrapped__
hänvisar nu alltid till den inkapslade funktionen, även om den funktionen definierade attributet__wrapped__
. (se bpo-17482)Ändrad i version 3.12: Attributet
__type_params__
kopieras nu som standard.
- @functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)¶
Detta är en bekvämlighetsfunktion för att anropa
update_wrapper()
som en funktionsdekorator när man definierar en omslagsfunktion. Den är likvärdig medpartial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)
. Till exempel:>>> from functools import wraps >>> def my_decorator(f): ... @wraps(f) ... def wrapper(*args, **kwds): ... print('Calling decorated function') ... return f(*args, **kwds) ... return wrapper ... >>> @my_decorator ... def example(): ... """Docstring""" ... print('Called example function') ... >>> example() Calling decorated function Called example function >>> example.__name__ 'example' >>> example.__doc__ 'Docstring'
Utan denna dekoratorfabrik skulle namnet på exempelfunktionen ha varit
'wrapper'
, och dokumentsträngen för den ursprungligaexample()
skulle ha gått förlorad.
partial
Objekt¶
partial
-objekt är anropsbara objekt som skapas av partial()
. De har tre skrivskyddade attribut:
- partial.func¶
Ett anropsbart objekt eller en funktion. Anrop till objektet
partial
kommer att vidarebefordras tillfunc
med nya argument och nyckelord.
- partial.args¶
De positionella argument längst till vänster som kommer att läggas till de positionella argument som anges i ett
partial
-objektanrop.
partial
-objekt är som funktionsobjekt i det att de är anropsbara, svagt refererbara och kan ha attribut. Det finns några viktiga skillnader. Exempelvis skapas inte attributen __name__
och __doc__
automatiskt.