8. Compound statements¶
Compound statements innehåller (grupper av) andra statements; de påverkar eller styr utförandet av dessa andra statements på något sätt. I allmänhet sträcker sig sammansatta statements över flera rader, men i enkla varianter kan en hel sammansatta statements rymmas på en rad.
Satserna if
, while
och for
implementerar traditionella kontrollflödeskonstruktioner. try
specificerar undantagshanterare och/eller uppstädningskod för en grupp satser, medan satsen with
gör det möjligt att exekvera initialiserings- och finaliseringskod runt ett kodblock. Funktions- och klassdefinitioner är också syntaktiskt sammansatta satser.
Ett sammansatt uttalande består av en eller flera ”klausuler” En klausul består av en rubrik och en ”svit” Klausulrubrikerna i en viss sammansatt sats har alla samma indragningsnivå. Varje klausulrubrik börjar med ett unikt identifierande nyckelord och slutar med kolon. En svit är en grupp satser som styrs av en klausul. En svit kan bestå av en eller flera semikolonseparerade enkla satser på samma rad som rubriken, efter rubrikens kolon, eller av en eller flera indragna satser på efterföljande rader. Endast den senare formen av en svit kan innehålla nästlade sammansatta satser; följande är olagligt, mest för att det inte skulle vara tydligt till vilken if
-sats en följande else
-sats skulle höra:
if test1: if test2: print(x)
Observera också att semikolon binder hårdare än kolon i detta sammanhang, så att i följande exempel utförs antingen alla eller inga av print()
-anropen:
if x < y < z: print(x); print(y); print(z)
Sammanfatta:
compound_stmt:if_stmt
|while_stmt
|for_stmt
|try_stmt
|with_stmt
|match_stmt
|funcdef
|classdef
|async_with_stmt
|async_for_stmt
|async_funcdef
suite:stmt_list
NEWLINE | NEWLINE INDENTstatement
+ DEDENT statement:stmt_list
NEWLINE |compound_stmt
stmt_list:simple_stmt
(";"simple_stmt
)* [";"]
Observera att satser alltid avslutas med en NEWLINE
, eventuellt följd av en DEDENT
. Observera också att valfria fortsättningssatser alltid börjar med ett nyckelord som inte kan börja en sats, så det finns inga tvetydigheter (problemet med ”dinglande else
” löses i Python genom att kräva att nästlade if
-satser är indragna).
I formateringen av grammatikreglerna i följande avsnitt placeras varje sats på en separat rad för tydlighetens skull.
8.1. Nyckelordet: !if-satsen¶
Satsen if
används för villkorlig exekvering:
if_stmt: "if"assignment_expression
":"suite
("elif"assignment_expression
":"suite
)* ["else" ":"suite
]
Den väljer exakt en av sviterna genom att utvärdera uttrycken ett efter ett tills ett av dem visar sig vara sant (se avsnitt Booleska operationer för definition av true och false); då körs den sviten (och ingen annan del av if
-satsen körs eller utvärderas). Om alla uttryck är falska, utförs sviten i else
-satsen, om den finns.
8.2. Nyckelordet: !while-satsen¶
Satsen while
används för upprepad exekvering så länge som ett uttryck är sant:
while_stmt: "while"assignment_expression
":"suite
["else" ":"suite
]
Detta testar uttrycket upprepade gånger och, om det är sant, körs den första sviten; om uttrycket är falskt (vilket kan vara första gången det testas) körs sviten i else
-satsen, om den finns, och slingan avslutas.
En break
-sats som exekveras i den första sviten avslutar slingan utan att exekvera else
-satsens svit. En continue
-sats som exekveras i den första sviten hoppar över resten av sviten och går tillbaka till att testa uttrycket.
8.3. for
-satsen¶
Satsen for
används för att iterera över elementen i en sekvens (t.ex. en sträng, tupel eller lista) eller ett annat itererbart objekt:
for_stmt: "for"target_list
"in"starred_expression_list
":"suite
["else" ":"suite
]
Uttrycket starred_expression_list
utvärderas en gång; det bör ge ett iterable-objekt. En iterator skapas för denna iterable. Det första objektet som tillhandahålls av iteratorn tilldelas sedan till mållistan med hjälp av standardreglerna för tilldelningar (se Uppdragsinformation), och sviten exekveras. Detta upprepas för varje objekt som tillhandahålls av iteratorn. När iteratorn är uttömd körs sviten i else
-satsen, om den finns, och loopen avslutas.
En break
-sats som exekveras i den första sviten avslutar slingan utan att exekvera else
-satsens svit. En continue
-sats som utförs i den första sviten hoppar över resten av sviten och fortsätter med nästa objekt, eller med else
-satsen om det inte finns något nästa objekt.
For-slingan gör tilldelningar till variablerna i mållistan. Detta skriver över alla tidigare tilldelningar till dessa variabler, inklusive de som gjorts i sviten av for-slingan:
för i inom intervall(10):
print(i)
i = 5 # detta kommer inte att påverka for-slingan
# eftersom i kommer att skrivas över med nästa
# index i intervallet
Namnen i mållistan raderas inte när slingan är klar, men om sekvensen är tom kommer de inte alls att ha tilldelats av slingan. Tips: Den inbyggda typen range()
representerar oföränderliga aritmetiska sekvenser av heltal. Till exempel ger iterering av range(3)
successivt 0, 1 och sedan 2.
Ändrad i version 3.11: Stjärnmärkta element är nu tillåtna i uttrycksförteckningen.
8.4. try
-satsen¶
Satsen try
specificerar undantagshanterare och/eller upprensningskod för en grupp satser:
try_stmt:try1_stmt
|try2_stmt
|try3_stmt
try1_stmt: "try" ":"suite
("except" [expression
["as"identifier
]] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try2_stmt: "try" ":"suite
("except" "*"expression
["as"identifier
] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try3_stmt: "try" ":"suite
"finally" ":"suite
Ytterligare information om undantag finns i avsnittet Undantag, och information om hur man använder raise
för att generera undantag finns i avsnittet raise-satsen.
Ändrad i version 3.14: Stöd för att eventuellt släppa grupperingsparenteser när flera undantagstyper används. Se PEP 758.
8.4.1. except
klausul¶
Klausulen except
specificerar en eller flera undantagshanterare. När inget undantag inträffar i try
-satsen utförs ingen undantagshanterare. När ett undantag inträffar i try
-sviten startas en sökning efter en undantagshanterare. Denna sökning inspekterar except
-klausulerna i tur och ordning tills en hittas som matchar undantaget. En uttryckslös except
-klausul, om den finns, måste vara sist; den matchar alla undantag.
För en except
-klausul med ett uttryck måste uttrycket utvärderas till en undantagstyp eller en tupel av undantagstyper. Parenteser kan utelämnas om flera undantagstyper anges och as
-satsen inte används. Det uppkomna undantaget matchar en except
-sats vars uttryck utvärderas till klassen eller en icke-virtuell basklass för undantagsobjektet, eller till en tupel som innehåller en sådan klass.
Om ingen except
-klausul matchar undantaget fortsätter sökandet efter en undantagshanterare i den omgivande koden och på anropsstacken. [1]
Om utvärderingen av ett uttryck i rubriken till en except
-sats ger upphov till ett undantag, avbryts den ursprungliga sökningen efter en hanterare och en sökning efter det nya undantaget påbörjas i den omgivande koden och på anropsstacken (det behandlas som om hela try
-satsen gav upphov till undantaget).
När en matchande except
-klausul hittas, tilldelas undantaget till det mål som anges efter as
-keywordet i den except
-klausulen, om det finns, och except
-klausulens svit exekveras. Alla except
-klausuler måste ha ett exekverbart block. När slutet av detta block nås, fortsätter exekveringen normalt efter hela try
-satsen. (Detta innebär att om det finns två nästlade hanterare för samma undantag, och undantaget inträffar i try
-satsen i den inre hanteraren, kommer den yttre hanteraren inte att hantera undantaget)
När ett undantag har tilldelats med hjälp av as target
, rensas det i slutet av except
-satsen. Detta är som om
utom E som N:
foo
översattes till
utom E som N:
try:
foo
slutligen: foo
del N
Detta innebär att undantaget måste tilldelas ett annat namn för att kunna referera till det efter except
-klausulen. Undantag rensas eftersom de med den spårning som är kopplad till dem bildar en referenscykel med stapelramen, vilket håller alla lokala objekt i den ramen vid liv tills nästa skräpsamling sker.
Innan en except
-klausuls svit exekveras lagras undantaget i modulen sys
, där det kan nås från except
-klausulens kropp genom att anropa sys.exception()
. När du lämnar en undantagshanterare återställs undantaget som lagrats i modulen sys
till sitt tidigare värde:
>>> print(sys.exception())
None
>>> try:
... raise TypeError
... except:
... print(repr(sys.exception()))
... try:
... raise ValueError
... except:
... print(repr(sys.exception()))
... print(repr(sys.exception()))
...
TypeError()
ValueError()
TypeError()
>>> print(sys.exception())
None
8.4.2. except*
klausul¶
Klausulerna except*
används för att hantera ExceptionGroup
. Undantagstypen för matchning tolkas som i fallet med except
, men i fallet med undantagsgrupper kan vi ha partiella matchningar när typen matchar några av undantagen i gruppen. Detta innebär att flera except*
-klausuler kan köras, var och en hanterar en del av undantagsgruppen. Varje klausul exekveras högst en gång och hanterar en undantagsgrupp med alla matchande undantag. Varje undantag i gruppen hanteras av högst en except*
-sats, den första som matchar det.
>>> try:
... raise ExceptionGroup("eg",
... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
... except* TypeError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
... except* OSError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
...
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 2, in <module>
| ExceptionGroup: eg
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
Eventuella återstående undantag som inte hanterades av någon except*
-klausul tas upp igen i slutet, tillsammans med alla undantag som togs upp från except*
-klausulerna. Om denna lista innehåller mer än ett undantag som ska tas upp på nytt, kombineras de till en undantagsgrupp.
Om det undantag som tas upp inte är en undantagsgrupp och dess typ matchar en av except*
-klausulerna, fångas det upp och omsluts av en undantagsgrupp med en tom meddelandesträng.
>>> try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError()))
En except*
-klausul måste ha ett matchande uttryck; det kan inte vara except*:
. Dessutom kan detta uttryck inte innehålla undantagsgrupptyper, eftersom det skulle ha en tvetydig semantik.
Det är inte möjligt att blanda except
och except*
i samma try
. break
, continue
och return
kan inte förekomma i en except*
-sats.
8.4.3. else
klausul¶
Den valfria else
-klausulen exekveras om kontrollflödet lämnar try
-sviten, inget undantag har uppstått och ingen return
-, continue
- eller break
-sats har exekverats. Undantag i else
-klausulen hanteras inte av de föregående except
-klausulerna.
8.4.4. finally
klausul¶
Om finally
finns med, anger det en ”cleanup”-hanterare. Klausulen try
exekveras, inklusive eventuella klausuler except
och else
. Om ett undantag inträffar i någon av klausulerna och inte hanteras, sparas undantaget temporärt. Klausulen finally
exekveras. Om det finns ett sparat undantag återkommer det i slutet av finally
-klausulen. Om klausulen finally
ger upphov till ett annat undantag, sätts det sparade undantaget som kontext för det nya undantaget. Om finally
-satsen exekverar en return
-, break
- eller continue
-sats, kasseras det sparade undantaget. Den här funktionen returnerar till exempel 42.
def f():
försök:
1/0
slutligen:
retur 42
Undantagsinformationen är inte tillgänglig för programmet under exekveringen av finally
-satsen.
När en return
, break
eller continue
-sats exekveras i try
-sviten av en try
…finally
-sats, exekveras även finally
-klausulen ”på vägen ut”
Returvärdet för en funktion bestäms av den sista return
-satsen som exekveras. Eftersom finally
-satsen alltid exekveras, kommer en return
-sats som exekveras i finally
-satsen alltid att vara den sista som exekveras. Följande funktion returnerar ’finally’.
def foo():
try:
returnera 'try'
finally: return 'finally':
returnera 'finally'
Ändrad i version 3.8: Före Python 3.8 var en continue
-sats olaglig i finally
-satsen på grund av ett problem med implementeringen.
Ändrad i version 3.14: Kompilatorn avger en SyntaxWarning
när ett return
, break
eller continue
förekommer i ett finally
-block (se PEP 765).
8.5. with
-satsen¶
Satsen with
används för att omsluta exekveringen av ett block med metoder som definieras av en kontexthanterare (se avsnitt Med uttalande från kontextansvariga). Detta gör att vanliga try
…except
…finally
användningsmönster kan kapslas in för bekväm återanvändning.
with_stmt: "with" ( "("with_stmt_contents
","? ")" |with_stmt_contents
) ":"suite
with_stmt_contents:with_item
(","with_item
)* with_item:expression
["as"target
]
Exekveringen av with
-satsen med ett ”objekt” går till på följande sätt:
Kontextuttrycket (det uttryck som anges i
with_item
) utvärderas för att få fram en kontexthanterare.Kontexthanterarens
__enter__()
laddas för senare användning.Kontexthanterarens
__exit__()
laddas för senare användning.Kontexthanterarens metod
__enter__()
anropas.Om ett mål ingick i
with
-satsen tilldelas det returvärdet från__enter__()
.Anteckning
Satsen
with
garanterar att om metoden__enter__()
returneras utan fel, så kommer__exit__()
alltid att anropas. Om ett fel inträffar under tilldelningen till mållistan kommer det alltså att behandlas på samma sätt som ett fel som inträffar inom sviten skulle ha behandlats. Se steg 7 nedan.Sviten är genomförd.
Kontexthanterarens metod
__exit__()
anropas. Om ett undantag orsakade att sviten avslutades, skickas dess typ, värde och traceback som argument till__exit__()
. Annars anges treNone
-argument.Om sviten avslutades på grund av ett undantag och returvärdet från metoden
__exit__()
var falskt, återskapas undantaget. Om returvärdet var sant undertrycks undantaget och exekveringen fortsätter med det uttalande som följer påwith
-satsen.Om sviten avslutades av någon annan anledning än ett undantag ignoreras returvärdet från
__exit__()
, och exekveringen fortsätter på den normala platsen för den typ av avslut som gjordes.
Följande kod:
med EXPRESSION som MÅL:
SUITE
är semantiskt ekvivalent med:
manager = (Uttryck)
enter = typ(chef).__enter__
exit = typ(chef).__exit__
värde = enter(chef)
hit_except = Falsk
försök:
TARGET = värde
SUITE
undantag:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
slutligen:
if not hit_except:
exit(manager, Ingen, Ingen, Ingen)
Med mer än ett objekt bearbetas kontexthanterarna som om flera with
-satser var nästlade:
med A() som a, B() som b:
SUITE
är semantiskt ekvivalent med:
med A() som a:
med B() som b:
SUITE
Du kan också skriva kontexthanterare med flera objekt på flera rader om objekten omges av parenteser. Till exempel:
med (
A() som a,
B() som b,
):
SUITE
Ändrad i version 3.1: Stöd för flera kontextuttryck.
Ändrad i version 3.10: Stöd för att använda grupperingsparenteser för att dela upp uttalandet i flera rader.
8.6. match
-satsen¶
Tillagd i version 3.10.
Match-satsen används för mönstermatchning. Syntax:
match_stmt: 'match'subject_expr
":" NEWLINE INDENTcase_block
+ DEDENT subject_expr:star_named_expression
","star_named_expressions
? |named_expression
case_block: 'case'patterns
[guard
] ":"block
Anteckning
I detta avsnitt används enkla citationstecken för att beteckna mjuka nyckelord.
Mönstermatchning tar ett mönster som indata (efter case
) och ett ämnesvärde (efter match
). Mönstret (som kan innehålla undermönster) matchas mot ämnesvärdet. Utfallet är följande:
En lyckad eller misslyckad matchning (även kallad ett lyckat eller misslyckat mönster).
Möjlig bindning av matchade värden till ett namn. Förutsättningarna för detta diskuteras vidare nedan.
Nyckelorden match
och case
är mjuka nyckelord.
Se även
8.6.1. Översikt¶
Här följer en översikt över det logiska flödet i ett matchningsbesked:
Subjektuttrycket
subject_expr
utvärderas och ett resulterande subjektvärde erhålls. Om ämnesuttrycket innehåller ett kommatecken konstrueras en tupel med hjälp av standardreglerna.Varje mönster i ett
case_block
försöker matchas med ämnesvärdet. De specifika reglerna för framgång eller misslyckande beskrivs nedan. Matchningsförsöket kan också binda vissa eller alla fristående namn inom mönstret. De exakta reglerna för mönsterbindning varierar beroende på mönstertyp och anges nedan. Namnbindningar som görs under en lyckad mönstermatchning överlever det exekverade blocket och kan användas efter matchningssatsen.Anteckning
Vid misslyckade mönstermatchningar kan vissa undermönster lyckas. Förlita dig inte på att bindningar görs för en misslyckad matchning. Omvänt ska du inte förlita dig på att variabler förblir oförändrade efter en misslyckad matchning. Det exakta beteendet är beroende av implementeringen och kan variera. Detta är ett avsiktligt beslut som fattats för att olika implementationer ska kunna lägga till optimeringar.
Om mönstret lyckas utvärderas motsvarande skydd (om sådant finns). I detta fall garanteras att alla namnbindningar har inträffat.
Om skyddet utvärderas som sant eller saknas, körs
block
inuticase_block
.I annat fall försöker nästa
case_block
enligt beskrivningen ovan.Om det inte finns några fler fallblock är matchningsöversikten klar.
Anteckning
Användare bör i allmänhet aldrig förlita sig på att ett mönster utvärderas. Beroende på implementering kan tolken cacha värden eller använda andra optimeringar som hoppar över upprepade utvärderingar.
Ett exempel på ett matchningsbesked:
>>> flag = False
>>> match (100, 200):
... case (100, 300): # Mismatch: 200 != 300
... print('Case 1')
... case (100, 200) if flag: # Successful match, but guard fails
... print('Case 2')
... case (100, y): # Matches and binds y to 200
... print(f'Case 3, y: {y}')
... case _: # Pattern not attempted
... print('Case 4, I match anything!')
...
Case 3, y: 200
I det här fallet är if flag
en guard. Läs mer om det i nästa avsnitt.
8.6.2. Vakter¶
guard: "if" named_expression
En guard
(som är en del av case
) måste lyckas för att koden i case
-blocket ska kunna exekveras. Den har formen: if
följt av ett uttryck.
Det logiska flödet i ett case
-block med en guard
är följande:
Kontrollera att mönstret i
case
-blocket lyckades. Om mönstret misslyckades utvärderas integuard
och nästacase
-block kontrolleras.Om mönstret lyckades, utvärdera
guard
.Om villkoret
guard
utvärderas som sant, väljs fallblocket.Om villkoret
guard
utvärderas som falskt, väljs inte ärendeblocket.Om
guard
ger upphov till ett undantag under utvärderingen, bubblar undantaget upp.
Guards får ha bieffekter eftersom de är uttryck. Guard-utvärderingen måste gå från det första till det sista fallblocket, ett i taget, och hoppa över fallblock där inte alla mönster lyckas. (D.v.s. utvärderingen av guarden måste ske i ordning.) Utvärderingen av guarden måste avbrytas när ett fallblock har valts.
8.6.3. Obestridliga fallblock¶
Ett obestridligt fallblock är ett match-all fallblock. Ett matchningsuttalande kan ha högst ett oåterkalleligt fallblock och det måste vara det sista.
Ett case-block anses vara oåterkalleligt om det inte har någon guard och om dess mönster är oåterkalleligt. Ett mönster anses vara oåterkalleligt om vi enbart utifrån dess syntax kan bevisa att det alltid kommer att lyckas. Endast följande mönster är oåterkalleliga:
AS-mönster vars vänstra sida är oåterkallelig
OR-mönster som innehåller minst ett obestridligt mönster
parentes ovedersägliga mönster
8.6.4. Blockmönster¶
Anteckning
I detta avsnitt används grammatiska notationer utöver standard EBNF:
notationen
SEP.RULE+
är en förkortning förRULE (SEP RULE)*
notationen
!RULE
är en förkortning för ett negativt framåtblickande påstående
Syntaxen på högsta nivå för patterns
är:
patterns:open_sequence_pattern
|pattern
pattern:as_pattern
|or_pattern
closed_pattern: |literal_pattern
|capture_pattern
|wildcard_pattern
|value_pattern
|group_pattern
|sequence_pattern
|mapping_pattern
|class_pattern
Beskrivningarna nedan innehåller en beskrivning ”i enkla ordalag” av vad ett mönster gör i illustrationssyfte (tack till Raymond Hettinger för ett dokument som inspirerat de flesta av beskrivningarna). Observera att dessa beskrivningar endast är avsedda som illustrationer och måste inte återspegla den underliggande implementeringen. Dessutom täcker de inte alla giltiga former.
8.6.4.1. OR-mönster¶
Ett OR-mönster är två eller flera mönster åtskilda av vertikala streck |
. Syntax:
or_pattern: "|".closed_pattern
+
Endast det sista undermönstret kan vara irrefutable, och varje undermönster måste binda samma uppsättning namn för att undvika tvetydighet.
Ett OR-mönster matchar vart och ett av sina undermönster i tur och ordning med ämnesvärdet, tills ett lyckas. OR-mönstret anses då vara framgångsrikt. I annat fall, om inget av undermönstren lyckas, misslyckas OR-mönstret.
Enkelt uttryckt kommer P1 | P2 | ...
att försöka matcha P1
, om det misslyckas kommer det att försöka matcha P2
, lyckas omedelbart om någon lyckas, misslyckas annars.
8.6.4.2. AS-mönster¶
Ett AS-mönster matchar ett OR-mönster till vänster om nyckelordet as
mot ett ämne. Syntax för detta:
as_pattern:or_pattern
"as"capture_pattern
Om OR-mönstret misslyckas, misslyckas AS-mönstret. I annat fall binder AS-mönstret subjektet till namnet till höger om as-nyckelordet och lyckas. capture_pattern
kan inte vara en _
.
Enkelt uttryckt kommer P as NAME
att matcha med P
, och vid framgång kommer den att sätta NAME = <subject>
.
8.6.4.3. Bokstavliga mönster¶
Ett bokstavsmönster motsvarar de flesta literals i Python. Syntax:
literal_pattern:signed_number
|signed_number
"+" NUMBER |signed_number
"-" NUMBER |strings
| "None" | "True" | "False" signed_number: ["-"] NUMBER
Regeln strings
och token NUMBER
är definierade i standard Python grammar. Trippelciterade strängar stöds. Råa strängar och byte-strängar stöds. f-strängar och t-strängar stöds inte.
Formerna signed_number '+' NUMBER
och signed_number '-' NUMBER
är till för att uttrycka komplexa tal; de kräver ett reellt tal till vänster och ett imaginärt tal till höger. T.ex. 3 + 4j
.
Enkelt uttryckt kommer LITERAL
att lyckas endast om <subject> == LITERAL
. För singletonerna None
, True
och False
används operatorn is
.
8.6.4.4. Fångstmönster¶
Ett capture-mönster binder ämnesvärdet till ett namn. Syntax:
capture_pattern: !'_' NAME
En enda understrykning _
är inte ett fångstmönster (det är vad !'_'
uttrycker). Det behandlas istället som en wildcard_pattern
.
I ett givet mönster kan ett givet namn bara bindas en gång. T.ex. case x, x: ...
är ogiltigt medan case [x] | x: ...
är tillåtet.
Fångstmönster lyckas alltid. Bindningen följer scoping-regler som fastställts av operatorn för tilldelningsuttryck i PEP 572; namnet blir en lokal variabel i den närmaste innehållande funktionens scope om det inte finns ett tillämpligt global
eller nonlocal
uttalande.
Enkelt uttryckt kommer NAME
alltid att lyckas och den kommer att ställa in NAME = <subject>
.
8.6.4.5. Jokerteckenmönster¶
Ett jokerteckenmönster är alltid framgångsrikt (matchar allt) och binder inget namn. Syntax för:
wildcard_pattern: '_'
_
är ett mjukt nyckelord inom alla mönster, men bara inom mönster. Det är en identifierare, som vanligt, även inom match
ämnesuttryck, guard
och case
block.
Enkelt uttryckt kommer _
alltid att lyckas.
8.6.4.6. Värdemönster¶
Ett värdemönster representerar ett namngivet värde i Python. Syntaxen är
value_pattern:attr
attr:name_or_attr
"." NAME name_or_attr:attr
| NAME
Det prickade namnet i mönstret söks upp med hjälp av standardreglerna för namnuppslagning i Python name resolution rules. Mönstret är korrekt om det värde som hittas är lika med det sökta värdet (med hjälp av jämlikhetsoperatorn ==
).
Enkelt uttryckt kommer NAME1.NAME2
att lyckas endast om <subject> == NAME1.NAME2
Anteckning
Om samma värde förekommer flera gånger i samma matchningsuttalande kan tolken cacha det första värdet som hittas och återanvända det i stället för att upprepa samma uppslagning. Denna cache är strikt knuten till en viss exekvering av en viss matchningssats.
8.6.4.7. Gruppmönster¶
Ett gruppmönster gör det möjligt för användare att lägga till parenteser runt mönster för att betona den avsedda grupperingen. I övrigt har det ingen ytterligare syntax. Syntax för gruppmönster:
group_pattern: "(" pattern
")"
Enkelt uttryckt har (P)
samma effekt som P
.
8.6.4.8. Sekvensmönster¶
Ett sekvensmönster innehåller flera undermönster som ska matchas mot sekvenselement. Syntaxen liknar uppackningen av en lista eller tupel.
sequence_pattern: "[" [maybe_sequence_pattern
] "]" | "(" [open_sequence_pattern
] ")" open_sequence_pattern:maybe_star_pattern
"," [maybe_sequence_pattern
] maybe_sequence_pattern: ",".maybe_star_pattern
+ ","? maybe_star_pattern:star_pattern
|pattern
star_pattern: "*" (capture_pattern
|wildcard_pattern
)
Det är ingen skillnad om parenteser eller hakparenteser används för sekvensmönster (t.ex. (...)
vs [...]
).
Anteckning
Ett enskilt mönster inom parentes utan efterföljande kommatecken (t.ex. (3 | 4)
) är ett gruppmönster. Medan ett enskilt mönster inom hakparenteser (t.ex. [3 | 4]
) fortfarande är ett sekvensmönster.
Högst ett stjärnundermönster kan finnas i ett sekvensmönster. Stjärnsubmönstret kan förekomma i vilken position som helst. Om inget stjärnundermönster förekommer är sekvensmönstret ett sekvensmönster med fast längd; annars är det ett sekvensmönster med variabel längd.
Följande är det logiska flödet för att matcha ett sekvensmönster mot ett ämnesvärde:
Om ämnesvärdet inte är en sekvens [2] misslyckas sekvensmönstret.
Om ämnesvärdet är en instans av
str
,bytes
ellerbytearray
misslyckas sekvensmönstret.De följande stegen beror på om sekvensmönstret är fast eller har variabel längd.
Om sekvensmönstret är av fast längd:
Om längden på den aktuella sekvensen inte är lika med antalet undermönster misslyckas sekvensmönstret
Submönster i sekvensmönstret matchas med motsvarande objekt i ämnessekvensen från vänster till höger. Matchningen stoppas så snart ett undermönster misslyckas. Om alla undermönster lyckas matcha sina motsvarande objekt, lyckas sekvensmönstret.
Annars, om sekvensmönstret är av variabel längd:
Om längden på den aktuella sekvensen är mindre än antalet icke-stjärnformade undermönster misslyckas sekvensmönstret.
De ledande icke-stjärniga undermönstren matchas med sina motsvarande objekt på samma sätt som för sekvenser med fast längd.
Om föregående steg lyckas, matchar det stjärnformade undermönstret en lista som består av de återstående ämnesobjekten, exklusive de återstående objekt som motsvarar icke-stjärnformade undermönster som följer på det stjärnformade undermönstret.
Återstående submönster som inte är stjärnformade matchas med motsvarande ämnesord, precis som för en sekvens med fast längd.
Anteckning
Längden på ämnessekvensen erhålls via
len()
(dvs. via protokollet__len__()
). Denna längd kan cachelagras av tolkaren på liknande sätt som value patterns.
Enkelt uttryckt [P1, P2, P3,
… , P<N>]
matchar endast om alla följande händelser inträffar:
kontrollera
<subject>
är en sekvenslen(subject) == <N>
P1
matchar<subject>[0]
(observera att denna matchning också kan binda namn)P2
matchar<subject>[1]
(observera att denna matchning också kan binda namn)… och så vidare för motsvarande mönster/element.
8.6.4.9. Kartläggning av mönster¶
Ett mappningsmönster innehåller ett eller flera nyckel-värde-mönster. Syntaxen liknar konstruktionen av en ordbok. Syntax för:
mapping_pattern: "{" [items_pattern
] "}" items_pattern: ",".key_value_pattern
+ ","? key_value_pattern: (literal_pattern
|value_pattern
) ":"pattern
|double_star_pattern
double_star_pattern: "**"capture_pattern
Högst ett dubbelstjärnmönster får finnas i ett mappningsmönster. Dubbelstjärnmönstret måste vara det sista undermönstret i mappningsmönstret.
Duplicerade nycklar i mappningsmönster är inte tillåtna. Duplicerade bokstavliga nycklar ger upphov till ett SyntaxError
. Två nycklar som annars har samma värde kommer att ge upphov till ett ValueError
vid körning.
Följande är det logiska flödet för att matcha ett mappningsmönster mot ett ämnesvärde:
Om ämnesvärdet inte är en mappning [3] misslyckas mappningsmönstret.
Om varje nyckel som anges i mappningsmönstret finns i ämnesmappningen och mönstret för varje nyckel matchar motsvarande post i ämnesmappningen, lyckas mappningsmönstret.
Om duplicerade nycklar upptäcks i mappningsmönstret anses mönstret vara ogiltigt. Ett
SyntaxError
uppstår för duplicerade bokstavliga värden; eller ettValueError
för namngivna nycklar med samma värde.
Anteckning
Nyckel-värde-par matchas med hjälp av tvåargumentformen av mappningsobjektets metod get()
. Matchade nyckel-värdepar måste redan finnas i mappningen och får inte skapas i farten via __missing__()
eller __getitem__()
.
Enkelt uttryckt {KEY1: P1, KEY2: P2, ... }
matchar endast om alla följande händelser inträffar:
kontrollera att
<subject>
är en mappningKEY1 in <subject>
P1
matchar<subject>[KEY1]
… och så vidare för motsvarande KEY/mönsterpar.
8.6.4.10. Klassmönster¶
Ett klassmönster representerar en klass och dess positions- och nyckelordsargument (om sådana finns). Syntaxen är
class_pattern:name_or_attr
"(" [pattern_arguments
","?] ")" pattern_arguments:positional_patterns
[","keyword_patterns
] |keyword_patterns
positional_patterns: ",".pattern
+ keyword_patterns: ",".keyword_pattern
+ keyword_pattern: NAME "="pattern
Samma nyckelord bör inte upprepas i klassmönster.
Följande är det logiska flödet för att matcha ett klassmönster mot ett ämnesvärde:
Om
name_or_attr
inte är en instans av den inbyggdatype
, raiseTypeError
.Om ämnesvärdet inte är en instans av
name_or_attr
(testas viaisinstance()
) misslyckas klassmönstret.Om det inte finns några mönsterargument lyckas mönstret. I annat fall beror de efterföljande stegen på om det finns nyckelords- eller positionsargumentmönster.
För ett antal inbyggda typer (specificeras nedan) accepteras ett enda positionellt undermönster som matchar hela ämnet; för dessa typer fungerar nyckelordsmönster också som för andra typer.
Om det bara finns nyckelordsmönster behandlas de enligt följande, ett efter ett:
I. Nyckelordet ses som ett attribut i ämnet.
Om detta ger upphov till ett annat undantag än
AttributeError
, bubblar undantaget upp.Om detta ger upphov till
AttributeError
, har klassmönstret misslyckats.Annars matchas det undermönster som är associerat med nyckelordsmönstret mot subjektets attributvärde. Om detta misslyckas, misslyckas klassmönstret; om detta lyckas, fortsätter matchningen till nästa nyckelord.
II. Om alla nyckelordsmönster lyckas, lyckas klassmönstret.
Om det finns positionella mönster konverteras de till nyckelordsmönster med hjälp av attributet
__match_args__
på klassenname_or_attr
före matchning:I. Motsvarigheten till
getattr(cls, "__match_args__", ())
anropas.Om detta ger upphov till ett undantag, bubblar undantaget upp.
Om det returnerade värdet inte är en tupel misslyckas konverteringen och
TypeError
aktiveras.Om det finns fler positionsmönster än
len(cls.__match_args__)
, uppstårTypeError
.Annars konverteras det positionella mönstret
i
till ett nyckelordsmönster med__match_args__[i]
som nyckelord.__match_args__[i]
måste vara en sträng; om inteTypeError
tas upp.Om det finns dubbla nyckelord kommer
TypeError
att tas upp.
- II. När alla positionsmönster har omvandlats till sökordsmönster,
matchningen fortsätter som om det bara fanns nyckelordsmönster.
För följande inbyggda typer är hanteringen av positionella submönster annorlunda:
Dessa klasser accepterar ett enda positionellt argument, och mönstret där matchas mot hela objektet snarare än ett attribut. Till exempel
int(0|1)
matchar värdet0
, men inte värdet0,0
.
Enkelt uttryckt CLS(P1, attr=P2)
matchar endast om följande inträffar:
isinstance(<subject>, CLS)
konvertera
P1
till ett nyckelordsmönster medCLS.__match_args__
För varje nyckelordsargument
attr=P2
:hasattr(<subject>, "attr")
P2
matchar<subject>.attr
… och så vidare för motsvarande nyckelordsargument/mönsterpar.
8.7. Definitioner av funktioner¶
En funktionsdefinition definierar ett användardefinierat funktionsobjekt (se avsnitt Standardtypens hierarki):
funcdef: [decorators
] "def"funcname
[type_params
] "(" [parameter_list
] ")" ["->"expression
] ":"suite
decorators:decorator
+ decorator: "@"assignment_expression
NEWLINE parameter_list:defparameter
(","defparameter
)* "," "/" ["," [parameter_list_no_posonly
]] |parameter_list_no_posonly
parameter_list_no_posonly:defparameter
(","defparameter
)* ["," [parameter_list_starargs
]] |parameter_list_starargs
parameter_list_starargs: "*" [star_parameter
] (","defparameter
)* ["," [parameter_star_kwargs
]] | "*" (","defparameter
)+ ["," [parameter_star_kwargs
]] |parameter_star_kwargs
parameter_star_kwargs: "**"parameter
[","] parameter:identifier
[":"expression
] star_parameter:identifier
[":" ["*"]expression
] defparameter:parameter
["="expression
] funcname:identifier
En funktionsdefinition är en exekverbar sats. När den exekveras binds funktionsnamnet i den aktuella lokala namnrymden till ett funktionsobjekt (ett omslag runt den exekverbara koden för funktionen). Detta funktionsobjekt innehåller en referens till den aktuella globala namnrymden som den globala namnrymd som ska användas när funktionen anropas.
Funktionsdefinitionen exekverar inte funktionens kropp; denna exekveras först när funktionen anropas. [4]
En funktionsdefinition kan omslutas av ett eller flera decorator -uttryck. Dekoratoruttryck utvärderas när funktionen definieras, i det scope som innehåller funktionsdefinitionen. Resultatet måste vara en callable, som anropas med funktionsobjektet som enda argument. Det returnerade värdet är bundet till funktionsnamnet i stället för till funktionsobjektet. Flera dekoratorer tillämpas på ett nästlat sätt. Till exempel följande kod
@f1(arg)
@f2
def func(): pass
är ungefär likvärdigt med
def func(): pass
func = f1(arg)(f2(func))
förutom att den ursprungliga funktionen inte är temporärt bunden till namnet func
.
Ändrad i version 3.9: Funktioner kan dekoreras med valfri giltig assignment_expression
. Tidigare var grammatiken mycket mer restriktiv; se PEP 614 för detaljer.
En lista med typ parametrar kan anges inom hakparentes mellan funktionens namn och den inledande parentesen för dess parameterlista. Detta indikerar för statiska typkontrollanter att funktionen är generisk. Vid körning kan typparametrarna hämtas från funktionens __type_params__
-attribut. Se Generiska funktioner för mer information.
Ändrad i version 3.12: Typ-parameterlistor är nya i Python 3.12.
När en eller flera parametrar har formen parameter =
uttryck, sägs funktionen ha ”default parameter values” För en parameter med ett standardvärde kan motsvarande argument utelämnas från ett anrop, varvid parameterns standardvärde ersätts. Om en parameter har ett standardvärde måste alla följande parametrar fram till ”*
” också ha ett standardvärde — detta är en syntaktisk restriktion som inte uttrycks av grammatiken.
Standardparametervärden utvärderas från vänster till höger när funktionsdefinitionen exekveras. Detta innebär att uttrycket utvärderas en gång när funktionen definieras och att samma ”förberäknade” värde används vid varje anrop. Detta är särskilt viktigt att förstå när ett standardparametervärde är ett föränderligt objekt, t.ex. en lista eller en ordbok: om funktionen ändrar objektet (t.ex. genom att lägga till ett objekt i en lista), ändras i själva verket standardparametervärdet. Detta är i allmänhet inte vad som var avsett. Ett sätt att komma runt detta är att använda None
som standard och uttryckligen testa för det i funktionens kropp, t.ex.:
def whats_on_the_telly(penguin=None):
om penguin är None:
penguin = []
penguin.append("djurparkens egendom")
returnera pingvin
Semantiken för funktionsanrop beskrivs mer i detalj i avsnitt Calls. Ett funktionsanrop tilldelar alltid värden till alla parametrar som nämns i parameterlistan, antingen från positionella argument, från nyckelordsargument eller från standardvärden. Om formen ”*identifier
” finns initialiseras den till en tupel som tar emot eventuella överflödiga positionella parametrar, med den tomma tupeln som standard. Om formen ”**identifier
” finns initieras den till en ny ordnad mappning som tar emot eventuella överflödiga nyckelordsargument, med en ny tom mappning av samma typ som standard. Parametrar efter ”*
” eller ”*identifier
” är endast nyckelordsparametrar och kan endast skickas med nyckelordsargument. Parametrar före ”/
” är endast positionsparametrar och kan endast överföras med positionsargument.
Ändrad i version 3.8: Syntaxen /
för funktionsparametrar kan användas för att ange parametrar som endast är positionella. Se PEP 570 för detaljer.
Parametrar kan ha en annotation av formen ”: expression
” efter parameternamnet. Alla parametrar kan ha en annotering, även de av formen *identifier
eller **identifier
. (Som ett specialfall kan parametrar av formen *identifier
ha annotationen ”: *expression
”) Funktioner kan ha en ”return”-annotation av formen ”-> expression
” efter parameterlistan. Dessa annotationer kan vara vilket giltigt Python-uttryck som helst. Förekomsten av annoteringar ändrar inte semantiken för en funktion. Se Anteckningar för mer information om annotationer.
Ändrad i version 3.11: Parametrar av formen ”*identifier
” kan ha en annotation ”: *uttryck
”. Se PEP 646.
Det är också möjligt att skapa anonyma funktioner (funktioner som inte är knutna till ett namn) för omedelbar användning i uttryck. Här används lambda-uttryck, som beskrivs i avsnitt Lambdas. Observera att lambdauttrycket bara är en förkortning för en förenklad funktionsdefinition; en funktion som definieras i en ”def
”-sats kan skickas runt eller tilldelas ett annat namn precis som en funktion som definieras av ett lambdauttryck. Formen ”def
” är faktiskt mer kraftfull eftersom den tillåter exekvering av flera satser och annoteringar.
Programmerarens anmärkning: Funktioner är första klassens objekt. En ”def
”-sats som exekveras inuti en funktionsdefinition definierar en lokal funktion som kan returneras eller skickas runt. Fria variabler som används i den nästlade funktionen kan komma åt de lokala variablerna i den funktion som innehåller def. Se avsnitt Namngivning och bindning för detaljer.
Se även
- PEP 3107 - Funktionskommentarer
Den ursprungliga specifikationen för funktionsannoteringar.
- PEP 484 - Tips om typ
Definition av en standardbetydelse för annotationer: typ hints.
- PEP 526 - Syntax för variabelkommentarer
Möjlighet att typhinta variabeldeklarationer, inklusive klassvariabler och instansvariabler.
- PEP 563 - Uppskjuten utvärdering av annoteringar
Stöd för framåtriktade referenser inom annotationer genom att bevara annotationer i strängform vid körning istället för ivrig utvärdering.
- PEP 318 - Dekoratorer för funktioner och metoder
Funktions- och metoddekoratorer introducerades. Klassdekoratorer introducerades i PEP 3129.
8.8. Klassdefinitioner¶
En klassdefinition definierar ett klassobjekt (se avsnitt Standardtypens hierarki):
classdef: [decorators
] "class"classname
[type_params
] [inheritance
] ":"suite
inheritance: "(" [argument_list
] ")" classname:identifier
En klassdefinition är ett körbart uttalande. Arvslistan ger vanligtvis en lista över basklasser (se Metaklasser för mer avancerade användningsområden), så varje objekt i listan bör utvärderas till ett klassobjekt som tillåter underklassning. Klasser utan en arvslista ärver, som standard, från basklassen object
; därav
klass Foo:
pass
är likvärdig med
klass Foo(objekt):
pass
Klassens svit exekveras sedan i en ny exekveringsram (se Namngivning och bindning), med en nyskapad lokal namnrymd och den ursprungliga globala namnrymden. (Vanligtvis innehåller sviten mest funktionsdefinitioner.) När klassens svit är färdig exekverad kasseras dess exekveringsram men dess lokala namnrymd sparas. [5] Ett klassobjekt skapas sedan med hjälp av arvslistan för basklasserna och det sparade lokala namnrymden för attributdictionariet. Klassnamnet är bundet till detta klassobjekt i den ursprungliga lokala namnrymden.
Den ordning i vilken attributen definieras i klassens kropp bevaras i den nya klassens __dict__
. Observera att detta endast är tillförlitligt direkt efter att klassen har skapats och endast för klasser som definierades med definitionssyntaxen.
Skapandet av klasser kan anpassas kraftigt med hjälp av metaclasses.
Klasser kan också dekoreras: precis som när du dekorerar funktioner,
@f1(arg)
@f2
klass Foo: pass
är ungefär likvärdigt med
klass Foo: pass
Foo = f1(arg)(f2(Foo))
Utvärderingsreglerna för dekoratoruttrycken är desamma som för funktionsdekoratorer. Resultatet binds sedan till klassnamnet.
Ändrad i version 3.9: Klasser kan dekoreras med valfri giltig assignment_expression
. Tidigare var grammatiken mycket mer restriktiv; se PEP 614 för detaljer.
En lista med typ-parametrar kan anges inom hakparenteser omedelbart efter klassens namn. Detta indikerar för statiska typkontrollanter att klassen är generisk. Vid körning kan typ-parametrarna hämtas från klassens __type_params__
-attribut. Se Generiska klasser för mer information.
Ändrad i version 3.12: Typ-parameterlistor är nya i Python 3.12.
Programmerarens anteckning: Variabler som definieras i klassdefinitionen är klassattribut; de delas av instanser. Instansattribut kan ställas in i en metod med self.name = value
. Både klass- och instansattribut är åtkomliga genom notationen ”self.name
”, och ett instansattribut döljer ett klassattribut med samma namn när det är åtkomligt på detta sätt. Klassattribut kan användas som standard för instansattribut, men att använda föränderliga värden där kan leda till oväntade resultat. Deskriptorer kan användas för att skapa instansvariabler med olika implementationsdetaljer.
Se även
- PEP 3115 - Metaklasser i Python 3000
Förslaget som ändrade deklarationen av metaklasser till den nuvarande syntaxen, och semantiken för hur klasser med metaklasser konstrueras.
- PEP 3129 - Klassdekoratorer
Förslaget som lade till klassdekoratorer. Funktions- och metoddekoratorer introducerades i PEP 318.
8.9. Coroutines¶
Tillagd i version 3.5.
8.9.1. Definition av Coroutine-funktion¶
async_funcdef: [decorators
] "async" "def"funcname
"(" [parameter_list
] ")" ["->"expression
] ":"suite
Exekveringen av Python coroutines kan avbrytas och återupptas på många ställen (se coroutine). uttrycken await
, async for
och async with
kan endast användas i en coroutine-funktion.
Funktioner som definieras med syntaxen async def
är alltid coroutine-funktioner, även om de inte innehåller nyckelorden await
eller async
.
Det är ett SyntaxError
att använda ett yield from
-uttryck inuti en coroutine-funktion.
Ett exempel på en coroutine-funktion:
async def func(param1, param2):
do_stuff()
await någon_coroutine()
Ändrad i version 3.7: await
och async
är nu nyckelord; tidigare behandlades de bara som sådana inom en coroutine-funktion.
8.9.2. Nyckelordet: !async for-satsen¶
async_for_stmt: "async" for_stmt
Ett asynchronous iterable tillhandahåller en __aiter__
-metod som direkt returnerar en asynchronous iterator, som kan anropa asynkron kod i sin __anext__
-metod.
Satsen async for
möjliggör bekväm iteration över asynkrona iterabler.
Följande kod:
asynkron för TARGET i ITER:
SUITE
annat:
SUITE2
Är semantiskt ekvivalent med:
iter = (ITER)
iter = typ(iter).__aiter__(iter)
kör = sant
medan körs:
try:
TARGET = await typ(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
Se även __aiter__()
och __anext__()
för mer information.
Det är ett SyntaxError
att använda en async for
-sats utanför kroppen på en coroutine-funktion.
8.9.3. Nyckelordet: !async with-satsen¶
async_with_stmt: "async" with_stmt
En asynchronous context manager är en context manager som kan avbryta exekveringen i sina enter- och exit-metoder.
Följande kod:
async med EXPRESSION som TARGET:
SUITE
är semantiskt ekvivalent med:
manager = (Uttryck)
aenter = typ(chef).__aenter__
aexit = typ(manager).__aexit__
value = await aenter(chef)
hit_except = Falsk
försök:
TARGET = värde
SUITE
undantag:
hit_except = True
if not await aexit(manager, *sys.exc_info()):
höjning
slutligen:
om inte hit_except:
await aexit(chef, Ingen, Ingen, Ingen)
Se även __aenter__()
och __aexit__()
för mer information.
Det är ett SyntaxError
att använda en async with
-sats utanför kroppen på en coroutine-funktion.
Se även
- PEP 492 - Coroutines med async- och await-syntax
Förslaget som gjorde coroutines till ett riktigt fristående koncept i Python och lade till stödjande syntax.
8.10. Typ parameterlistor¶
Tillagd i version 3.12.
Ändrad i version 3.13: Stöd för standardvärden har lagts till (se PEP 696).
type_params: "["type_param
(","type_param
)* "]" type_param:typevar
|typevartuple
|paramspec
typevar:identifier
(":"expression
)? ("="expression
)? typevartuple: "*"identifier
("="expression
)? paramspec: "**"identifier
("="expression
)?
Functions (inklusive coroutines), classes och type aliases kan innehålla en typ parameter list:
def max[T](args: list[T]) -> T:
...
async def amax[T](args: list[T]) -> T:
...
klass Bag[T]:
def __iter__(self) -> Iterator[T]:
...
def add(self, arg: T) -> None:
...
typ ListOrSet[T] = list[T] | set[T]
Semantiskt sett indikerar detta att funktionen, klassen eller typaliaset är generiskt över en typvariabel. Denna information används främst av statiska typkontrollanter, och vid körning beter sig generiska objekt ungefär som sina icke-generiska motsvarigheter.
Typparametrar deklareras inom hakparenteser ([]
) omedelbart efter namnet på funktionen, klassen eller typaliaset. Typ-parametrarna är åtkomliga inom det generiska objektets scope, men inte någon annanstans. Efter en deklaration def func[T](): pass
är således namnet T
inte tillgängligt i modulens scope. Nedan beskrivs semantiken för generiska objekt med större precision. Omfattningen av typparametrar modelleras med en speciell funktion (tekniskt sett en annotation scope) som omsluter skapandet av det generiska objektet.
Generiska funktioner, klasser och typaliaser har ett __type_params__
-attribut som listar deras typparametrar.
Det finns tre olika typer av parametrar:
typing.TypeVar
, inleds med ett vanligt namn (t.ex.T
). Semantiskt representerar detta en enda typ för en typkontrollör.typing.TypeVarTuple
, inleds med ett namn som föregås av en asterisk (t.ex.*Ts
). Semantiskt står detta för en tupel av valfritt antal typer.typing.ParamSpec
, inleds med ett namn som föregås av två asterisker (t.ex.**P
). Semantiskt står detta för parametrarna för en callable.
typing.TypeVar
-deklarationer kan definiera gränser och begränsningar med ett kolon (:
) följt av ett uttryck. Ett enda uttryck efter kolon anger en bound (t.ex. T: int
). Semantiskt innebär detta att typing.TypeVar
endast kan representera typer som är en subtyp av denna bound. En parentesförsedd tupel av uttryck efter kolon anger en uppsättning begränsningar (t.ex. T: (str, bytes)
). Varje medlem i tupeln bör vara en typ (återigen, detta verkställs inte vid körning). Variabler av typen Constrained kan bara anta en av typerna i listan med begränsningar.
För typing.TypeVar`
som deklareras med hjälp av syntaxen för typ-parameterlistan utvärderas inte bindningarna och begränsningarna när det generiska objektet skapas, utan endast när värdet uttryckligen nås via attributen __bound__
och __constraints__
. För att åstadkomma detta utvärderas gränserna eller begränsningarna i en separat annotation scope.
typing.TypeVarTuple
s och typing.ParamSpec
s kan inte ha gränser eller begränsningar.
Alla tre typerna av typparametrar kan också ha ett standardvärde, som används när typparametern inte anges explicit. Detta läggs till genom att lägga till ett enda likhetstecken (=
) följt av ett uttryck. Precis som typvariablernas gränser och begränsningar utvärderas inte standardvärdet när objektet skapas, utan först när typparameterns attribut __default__
används. Därför utvärderas standardvärdet i en separat annotation scope. Om inget standardvärde anges för en typparameter sätts attributet __default__
till det speciella sentinel-objektet typing.NoDefault
.
Följande exempel visar hela uppsättningen av tillåtna deklarationer av typparametrar:
def overly_generic[
SimpleTypeVar,
TypeVarWithDefault = int,
TypeVarWithBound: int,
TypeVarWithConstraints: (str, bytes),
*SimpleTypeVarTuple = (int, float),
**SimpleParamSpec = (str, bytearray),
](
a: SimpleTypeVar,
b: TypeVarWithDefault,
c: TypeVarWithBound,
d: Callable[SimpleParamSpec, TypeVarWithConstraints],
*e: SimpleTypeVarTuple,
): ...
8.10.1. Generiska funktioner¶
Generiska funktioner deklareras på följande sätt:
def func[T](arg: T): ...
Denna syntax är likvärdig med:
annotation-def TYPE_PARAMS_OF_func():
T = typing.TypeVar("T")
def func(arg: T): ...
func.__type_params__ = (T,)
returnera func
func = TYPE_PARAMS_OF_func()
Här anger annotation-def
en annotation scope, som inte är bunden till något namn vid körning. (En annan frihet tas i översättningen: syntaxen går inte genom attributåtkomst på modulen typing
, utan skapar en instans av typing.TypeVar
direkt)
Annoteringarna för generiska funktioner utvärderas inom det annoteringsområde som används för att deklarera typparametrarna, men det gör inte funktionens standardvärden och dekoratorer.
Följande exempel illustrerar scopingreglerna för dessa fall, samt för ytterligare varianter av typparametrar:
@dekorator
def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = some_default):
...
Med undantag för lazy evaluation av TypeVar
-bindningen, är detta likvärdigt med:
DEFAULT_OF_arg = någon_default
annotation-def TYPE_PARAMS_OF_func():
annotation-def BOUND_OF_T():
returnera int
# I verkligheten utvärderas BOUND_OF_T() endast på begäran.
T = typing.TypeVar("T", bound=BOUND_OF_T())
Ts = typing.TypeVarTuple("Ts")
P = typing.ParamSpec("P")
def func(*args: *Ts, arg: Callable[P, T] = DEFAULT_OF_arg):
...
func.__type_params__ = (T, Ts, P)
returnera func
func = dekorator(TYPE_PARAMS_OF_func())
De versala namnen som DEFAULT_OF_arg
är faktiskt inte bundna vid körning.
8.10.2. Generiska klasser¶
Generiska klasser deklareras på följande sätt:
class Bag[T]: ...
Denna syntax är likvärdig med:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(typing.Generic[T]):
__type_params__ = (T,)
...
returnera Bag
Bag = TYPE_PARAMS_OF_Bag()
Även här anger annotation-def
(inte ett riktigt nyckelord) en annotation scope, och namnet TYPE_PARAMS_OF_Bag
är inte faktiskt bundet vid körning.
Generiska klasser ärver implicit från typing.Generic
. Basklasserna och nyckelordsargumenten för generiska klasser utvärderas inom typomfånget för typparametrarna, och dekoratorer utvärderas utanför detta omfång. Detta illustreras av detta exempel:
@dekoratör
class Bag(Base[T], arg=T): ...
Detta är likvärdigt med:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(Base[T], typing.Generic[T], arg=T):
__type_params__ = (T,)
...
return Bag
Bag = dekorator(TYPE_PARAMS_OF_Bag())
8.10.3. Alias för generiska typer¶
Satsen type
kan också användas för att skapa ett generiskt typalias:
typ ListOrSet[T] = list[T] | set[T]
Med undantag för långsam utvärdering av värdet, är detta likvärdigt med:
annotation-def TYPE_PARAMS_OF_ListOrSet():
T = typing.TypeVar("T")
annotation-def VALUE_OF_ListOrSet():
return list[T] | set[T]
# I verkligheten utvärderas värdet lättsinnigt
return typing.TypeAliasType("ListOrSet", VALUE_OF_ListOrSet(), type_params=(T,))
ListOrSet = TYPE_PARAMS_OF_ListOrSet()
Här anger annotation-def
(inte ett riktigt nyckelord) en annotation scope. De versala namnen som TYPE_PARAMS_OF_ListOrSet
är faktiskt inte bundna vid körning.
8.11. Anteckningar¶
Ändrad i version 3.14: Annotationer utvärderas nu lättsamt som standard.
Variabler och funktionsparametrar kan ha annotationer, som skapas genom att lägga till ett kolon efter namnet, följt av ett uttryck:
x: anteckning = 1
def f(param: annotation): ...
Funktioner kan också ha en returannotering som följer en pil:
def f() -> annotation: ...
Annotationer används konventionellt för type hints, men detta är inte påtvingat av språket, och i allmänhet kan annotationer innehålla godtyckliga uttryck. Förekomsten av annoteringar ändrar inte kodens körtidssemantik, förutom om någon mekanism används som introspekterar och använder annoteringarna (t.ex. dataclasses
eller functools.singledispatch()
).
Som standard utvärderas annoteringar i ett annotation scope. Detta innebär att de inte utvärderas när koden som innehåller annotationen utvärderas. Istället sparar tolken information som kan användas för att utvärdera annotationen senare om så begärs. Modulen annotationlib
tillhandahåller verktyg för att utvärdera annotationer.
Om future-satsen from __future__ import annotations
är närvarande, lagras alla annotationer istället som strängar:
>>> from __future__ import annotations
>>> def f(param: annotation): ...
>>> f.__annotations__
{'param': 'annotation'}
Detta framtida uttalande kommer att vara föråldrat och tas bort i en framtida version av Python, men inte innan Python 3.13 når sitt livs slut (se PEP 749). När det används är det mindre sannolikt att introspektionsverktyg som annotationlib.get_annotations()
och typing.get_type_hints()
kan lösa annoteringar vid körning.
Fotnoter