Python-syntax och semantik

Syntaxen för programmeringsspråket Python är den uppsättning regler som definierar hur ett Python-program kommer att skrivas och tolkas ( av både runtime-systemet och av mänskliga läsare). Språket Python har många likheter med Perl , C och Java . Det finns dock vissa tydliga skillnader mellan språken.

Designfilosofi

Python designades för att vara ett mycket läsbart språk. Den har en relativt enkel visuell layout och använder ofta engelska nyckelord där andra språk använder skiljetecken . Python strävar efter att vara enkel och konsekvent i utformningen av sin syntax, inkapslad i mantrat "Det bör finnas ett - och helst bara ett - självklart sätt att göra det", från Zen of Python .

Detta mantra är medvetet emot Perl- och Ruby -mantrat, " det finns mer än ett sätt att göra det" .

Nyckelord

Python har 35 nyckelord eller reserverade ord ; de kan inte användas som identifierare .

  • och
  • som
  • hävda
  • asynkron
  • vänta
  • ha sönder
  • klass
  • Fortsätta
  • def
  • del
  • elif
  • annan
  • bortsett från
  • Falsk
  • till sist
  • för
  • från
  • global
  • om
  • importera
  • i
  • är
  • lambda
  • Ingen
  • icke-lokala
  • inte
  • eller
  • passera
  • höja
  • lämna tillbaka
  • Sann
  • Prova
  • medan
  • med
  • avkastning

Dessutom har Python också 3 mjuka nyckelord . Till skillnad från vanliga hårda sökord är mjuka sökord reserverade ord endast i de begränsade sammanhang där det skulle vara syntaktisk meningsfullt att tolka dem som nyckelord. Dessa ord kan användas som identifierare någon annanstans; Du kan definiera en funktion eller variabel med namnet matchning eller skiftläge .

  • _
  • fall
  • match
Anteckningar

Indrag

Python använder blanksteg för att avgränsa kontrollflödesblock (enligt off-side-regeln) . Python lånar den här funktionen från sin föregångare ABC : istället för skiljetecken eller nyckelord använder den indrag för att indikera körningen av ett block .

I så kallade "fritt format"-språk – som använder blockstrukturen härledd från ALGOL – sätts kodblock av med klammerparenteser ( { } ) eller nyckelord. I de flesta kodningskonventioner för dessa språk drar programmerare konventionellt in koden i ett block för att visuellt skilja den från den omgivande koden.

En rekursiv funktion som heter foo , som skickas en enskild parameter , x , och om parametern är 0 kommer att anropa en annan funktion som heter bar och annars anropar baz , passerar x , och även anropa sig själv rekursivt, och skickar x-1 som parameter , skulle kunna implementeras så här i Python:

 
       0
        
    
        
           def  foo  (  x  ):  om  x  ==  :  bar  ()  else  :  baz  (  x  )  foo  (  x  -  1  ) 

och skulle kunna skrivas så här i C med K&R indragsstil :

  

       0 
        
      
        
          
    
 void  foo  (  int  x  )  {  if  (  x  ==  )  {  bar  ();  }  annat  {  baz  (  x  );  foo  (  x  -  1  );  }  } 

Felaktigt indragen kod kan felläsas av en mänsklig läsare på ett annat sätt än den skulle tolkas av en kompilator eller tolk. Till exempel, om funktionsanropet foo(x - 1) på den sista raden i exemplet ovan felaktigt indragits för att vara utanför if / else -blocket:

 
       0
        
    
        
       def  foo  (  x  ):  om  x  ==  :  bar  ()  else  :  baz  (  x  )  foo  (  x  -  1  ) 

det skulle göra att den sista raden alltid exekveras, även när x är 0, vilket resulterar i en oändlig rekursion .

Även om både blanksteg och tabbtecken accepteras som former av indrag och valfri multipel av blanksteg kan användas, rekommenderas blanksteg och 4 blanksteg (som i exemplen ovan) rekommenderas och är den överlägset vanligaste. [ opålitlig källa? ] Att blanda mellanslag och flikar på rader i följd är inte tillåtet från och med Python 3 eftersom det kan skapa buggar som är svåra att se, eftersom många verktyg inte visuellt särskiljer mellanslag och flikar.

Data struktur

Eftersom Python är ett dynamiskt skrivet språk, innehåller Python- värden, inte variabler, typinformation . Alla variabler i Python innehåller referenser till objekt , och dessa referenser skickas till funktioner. Vissa människor (inklusive Guido van Rossum själv) har kallat detta parameteröverförande schema "anrop genom objektreferens". En objektreferens betyder ett namn, och den godkända referensen är ett "alias", dvs en kopia av referensen till samma objekt, precis som i C/ C++ . Objektets värde kan ändras i den anropade funktionen med "alias", till exempel:

    
 
    
    




 >>>  alist  =  [  'a'  ,  'b'  ,  'c'  ]  >>>  def  my_func  (  al  ):  ...  al  .  lägg till  (  'x'  )  ...  skriv ut  (  al  )  ...  >>>  my_func  (  alist  )  ['a', 'b', 'c', 'x']  >>>  alist  ['a', ' b', 'c', 'x'] 

Funktionen my_func ändrar värdet på alist med det formella argumentet al , som är ett alias för alist . Alla försök att använda (tilldela en ny objektreferens till) på själva aliaset kommer dock inte att ha någon effekt på det ursprungliga objektet. [ förtydligande behövs ]

    
 
    
         
    




 >>>  alist  =  [  'a'  ,  'b'  ,  'c'  ]  >>>  def  my_func  (  al  ):  ...  # al.append('x')  ...  al  =  al  +  [  'x'  ]  # en ny lista skapad och tilldelad till al betyder att al inte längre är alias för alist  ...  print  (  al  )  ...  >>>  my_func  (  alist  )  ['a', 'b', 'c', 'x ']  >>>  skriv ut  (  alist  )  ['a', 'b', 'c'] 

I Python är icke-innersta-lokala och inte-deklarerade-globala tillgängliga namn alla alias.

Bland dynamiskt typade språk är Python måttligt typkontrollerad. Implicit konvertering definieras för numeriska typer (såväl som booleans ), så man kan giltigt multiplicera ett komplext tal med ett heltal (till exempel) utan explicit casting . Det finns dock ingen implicit konvertering mellan till exempel tal och strängar ; en sträng är ett ogiltigt argument för en matematisk funktion som förväntar sig ett tal.

Bastyper

Python har ett brett utbud av grundläggande datatyper. Vid sidan av konventionell heltals- och flyttalsaritmetik stöder den på ett transparent sätt aritmetik med godtycklig precision , komplexa tal och decimaltal .

Python stöder en mängd olika strängoperationer. Strängar i Python är oföränderliga , så en strängoperation som en ersättning av tecken , som i andra programmeringsspråk kan ändra strängen på plats , returnerar en ny sträng i Python. Prestandaöverväganden tvingar ibland till att använda speciella tekniker i program som modifierar strängar intensivt, till exempel att sammanfoga teckenuppsättningar till strängar endast efter behov.

Samlingstyper

En av de mycket användbara aspekterna av Python är konceptet med insamlings- (eller containertyper ). I allmänhet är en samling ett objekt som innehåller andra objekt på ett sätt som lätt kan refereras eller indexeras . Samlingar finns i två grundläggande former: sekvenser och mappningar .

De ordnade sekventiella typerna är listor (dynamiska arrayer ), tupler och strängar. Alla sekvenser indexeras positionellt ( 0 till längd - 1 ) och alla utom strängar kan innehålla vilken typ av objekt som helst, inklusive flera typer i samma sekvens. Både strängar och tupler är oföränderliga, vilket gör dem till perfekta kandidater för ordboksnycklar (se nedan). Listor, å andra sidan, är föränderliga; element kan infogas, raderas, ändras, läggas till eller sorteras på plats .

Mappningar, å andra sidan, är (ofta oordnade) typer implementerade i form av ordböcker som "mappar" en uppsättning oföränderliga nycklar till motsvarande element (ungefär som en matematisk funktion). Till exempel skulle man kunna definiera en ordbok med en sträng "toast" mappad till heltal 42 eller vice versa. Nycklarna i en ordbok måste vara av en oföränderlig Python-typ, till exempel ett heltal eller en sträng, eftersom de under huven implementeras via en hashfunktion . Detta ger mycket snabbare uppslagstider, men kräver att nycklar inte ändras.

Ordböcker är centrala för Pythons inre delar eftersom de finns i kärnan av alla objekt och klasser: mappningarna mellan variabelnamn (strängar) och de värden som namnen refererar till lagras som ordböcker (se Objektsystem ) . Eftersom dessa ordböcker är direkt tillgängliga (via ett objekts __dict__- attribut), är metaprogrammering en enkel och naturlig process i Python.

En uppsättningssamlingstyp är en oindexerad, oordnad samling som inte innehåller några dubbletter och implementerar uppsättningsteoretiska operationer som union , intersection , difference , symmetrisk skillnad och delmängdstestning . Det finns två typer av set: set och frozenset , den enda skillnaden är att setet är föränderligt och frozenset är oföränderligt. Element i en uppsättning måste vara hashbara. Således kan till exempel en frusen uppsättning vara en del av en vanlig uppsättning medan motsatsen inte är sant.

Python tillhandahåller också omfattande samlingsmanipulerande förmågor som inbyggd kontroll av inneslutning och ett generiskt iterationsprotokoll.

Objektsystem

I Python är allt ett objekt, även klasser. Klasser, som objekt, har en klass, som är känd som deras metaklass . Python stöder också flera arv och mixins .

Språket stöder omfattande introspektion av typer och klasser. Typer kan läsas och jämföras – typer är instanser av typ . Attributen för ett objekt kan extraheras som en ordbok.

Operatörer kan överbelastas i Python genom att definiera speciella medlemsfunktioner – till exempel att definiera en metod som heter __add__ på en klass tillåter en att använda operatorn + på objekt i den klassen.

Bokstäver

Strängar

Python har olika typer av strängliteraler .

Normala strängbokstavar

Antingen enkla eller dubbla citattecken kan användas för att citera strängar. Till skillnad från i Unix-skalspråk, Perl- eller Perl-influerade språk som Ruby eller Groovy , fungerar enkla citattecken och dubbla citattecken identiskt, dvs det finns ingen stränginterpolation av $foo -uttryck. Interpolation kan dock göras på olika sätt: med "f-strängar" (sedan Python 3.6), med formatmetoden eller den gamla % -strängformatoperatorn.

Till exempel, alla dessa Python-satser:



 
 
 

   
      print  (  f  "Jag har precis skrivit ut  {  num  }  sidor till skrivaren  {  printer  }  "  )  print  (  "Jag har precis skrivit ut  {}  sidor till skrivaren  {}  "  .  format  (  num  ,  printer  ))  print  (  "Jag har precis skrivit ut  {0) }  sidor till skrivaren  {1}  "  .  format  (  num  ,  skrivare  ))  print  (  "Jag skrev precis ut  {num}  sidor till skrivaren  {printer}  "  .  format  (  num  =  num  ,  skrivare  =  skrivare  ))  print  (  "I har precis skrivit ut  %s  sidor till skrivaren  %s  "  %  (  num  ,  skrivare  ))  print  (  "Jag har precis skrivit ut  %(num)s  sidor till skrivaren  %(printer)s  "  %  {  "num"  :  num  ,  "printer"  :  skrivare  }) 

motsvarar Perl-påståendet:

  print  "Jag har precis skrivit ut $num sidor till skrivaren $printer\n" 

De bygger en sträng med hjälp av variablerna num och printer .

Flerradiga strängar

Det finns också flerradiga strängar, som börjar och slutar med en serie av tre enkla eller dubbla citattecken och fungerar som här dokument i Perl och Ruby .

Ett enkelt exempel med variabel interpolation (med formatmetoden ) är:







  print  (  '''Kära  {recipient}  ,  jag önskar att du lämnar Sunnydale och aldrig kommer tillbaka.  Not Quite Love,  {sender}  '''  .  format  (  avsändare  =  "Buffy the Vampire Slayer"  ,  mottagare  =  "Spike"  )) 

Råa strängar

Slutligen kommer alla de tidigare nämnda strängtyperna i " " varianter (betecknas genom att placera ett bokstavligt r före det inledande citatet), som inte gör någon omvänd snedstreck-interpolation och därför är mycket användbara för reguljära uttryck ; jämför "@-quoting" i C# . Råsträngar inkluderades ursprungligen specifikt för reguljära uttryck. På grund av tokenizerns begränsningar kanske råsträngar inte har ett bakåtstreck. Att skapa en obearbetad sträng som innehåller en Windows- sökväg som slutar med ett omvänt snedstreck kräver en mängd olika lösningar (vanligtvis använder snedstreck i stället för bakåtstreck, eftersom Windows accepterar båda).

Exempel inkluderar:



    
                     


   
              


  




 


  

  

 >>>  # En Windows-sökväg, även råsträngar kan inte sluta med ett snedstreck  >>>  r  "C:\Foo\Bar\Baz  \"  File  "<stdin>"  , rad  1  r  "C:\Foo\Bar\Baz  \"  ^  SyntaxError  :  EOL under scanning av strängen literal  >>>  dos_path  =  r  "C:\Foo\Bar\Baz\ "  # undviker felet genom att lägga till  >>>  dos_path  .  rstrip  ()  # och ta bort det efterföljande utrymmet  'C:\\Foo\\Bar\\Baz\\'  >>>  quoted_dos_path  =  r  ' "   {} "   '  .  format  (  dos_path  )  >>>  quoted_dos_path  '"C:\\Foo\\Bar\\Baz\\ "'  >>>  # Ett reguljärt uttryck som matchar en citerad sträng med eventuellt omvänt snedstreck som citerar  >>>  re  .  match  (  r  '"(([^"  \\  ]|  \\  .)*)"'  ,  quoted_dos_path  )  .  group  (  1  )  .  rstrip  ()  'C:\\Foo\\Bar\\Baz\\'  > >>  code  =  'foo(2, bar)'  >>>  # Vänd argumenten i ett tvåarg funktionsanrop  >>>  re  .  sub  (  r  '\(([^,]*?),([^ , ]*?)\)'  ,  r  '(\2, \1)'  ,  code  )  'foo(2, bar)'  >>>  # Observera att detta inte fungerar om något av argumenten har parens eller kommatecken. 

Sammanfogning av angränsande strängliteraler

Strängliteraler (med möjligen olika citatkonventioner) som visas sammanhängande och endast separerade av blanksteg (inklusive nya rader), är tillåtna och aggregeras till en enda längre sträng. Således

   title  =  "En bra sväng: " \ '  En  naturhistoria av skruvmejseln och skruven' 

är ekvivalent med

   title  =  "One Good Turn: A Natural History of the Screwdriver and the Screw" 

Unicode

Sedan Python 3.0 är standardteckenuppsättningen UTF-8 både för källkod och tolk. I UTF-8 hanteras unicode-strängar som traditionella bytesträngar. Detta exempel kommer att fungera:

   
 s  =  "Γειά"  # Hej på grekiska  tryck  (  s  ) 

Tal

0 Numeriska bokstaver i Python är av normal sort, t.ex. -1 , 3.4 , 3.5e -8 .

Python har heltal av godtycklig längd och ökar automatiskt deras lagringsstorlek vid behov. Före Python 3 fanns det två typer av heltal: traditionella heltal med fast storlek och "långa" heltal av godtycklig storlek. Omvandlingen till "långa" heltal utfördes automatiskt när det krävdes, och därför behövde programmeraren vanligtvis inte vara medveten om de två integraltyperna. I nyare språkversioner är distinktionen helt borta och alla heltal beter sig som heltal av godtycklig längd.

Python stöder normala flyttal , som skapas när en punkt används i en bokstavlig (t.ex. 1.1 ), när ett heltal och ett flyttal används i ett uttryck, eller som ett resultat av vissa matematiska operationer ("sann division" via operatorn / , eller exponentiering med en negativ exponent).

Python stöder också komplexa tal inbyggt. Komplexa tal indikeras med J eller j , t.ex. 3 + 4j .

Listor, tupler, uppsättningar, ordböcker

Python har syntaktisk stöd för att skapa containertyper.

Listor (klasslista) är föränderliga sekvenser av objekt av godtyckliga typer, och kan skapas antingen med den speciella syntaxen

      a_list  =  [  1  ,  2  ,  3  ,  "en hund"  ] 

eller genom att använda normalt objektskapande

  

 a_second_list  =  lista  ()  a_second_list  .  lägg till  (  4  )  en_andra_lista  .  bifoga  (  5  ) 

Tuples (klass tuple ) är oföränderliga sekvenser av föremål av godtyckliga typer. Det finns också en speciell syntax för att skapa tupler

     
      a_tuple  =  1  ,  2  ,  3  ,  "fyra"  a_tuple  =  (  1  ,  2  ,  3  ,  "fyra"  ) 

Även om tuplar skapas genom att separera objekt med kommatecken, är hela konstruktionen vanligtvis inslagen inom parentes för att öka läsbarheten. En tom tuppel betecknas med () , medan en tupel med ett enda värde kan skapas med (1,) .

Uppsättningar (klassuppsättning ) är föränderliga behållare med hashbara objekt av godtyckliga typer, utan dubbletter. Artiklarna är inte beställda, men ställer in supportiteration över artiklarna. Syntaxen för att skapa set använder parenteser

  0   some_set  =  {  ,  (),  False  } 

Python-uppsättningar är mycket som matematiska uppsättningar , och stödoperationer som uppsättningsskärning och union . Python har också en frozenset- klass för oföränderliga uppsättningar, se Samlingstyper .

Ordböcker (klass dict ) är föränderliga mappningar som knyter nycklar och motsvarande värden. Python har speciell syntax för att skapa ordböcker ( {nyckel: värde} )

        a_dictionary  =  {  "nyckel 1"  :  "värde 1"  ,  2  :  3  ,  4  :  []} 

Ordbokssyntaxen liknar den inställda syntaxen, skillnaden är närvaron av kolon. Den tomma bokstavliga {} resulterar i en tom ordbok snarare än en tom uppsättning, som istället skapas med den icke-literala konstruktorn: set() .

Operatörer

Aritmetisk

Python inkluderar operatorerna + , - , * , / ("sann division"), // ( våningsindelning ), % ( modul ) och ** ( exponentiering ) med deras vanliga matematiska företräde .

I Python 3 utför x/y "sann division", vilket betyder att den alltid returnerar ett float, även om både x och y är heltal som delar sig jämnt.

   >>>  4/2  2.0  _  _ 

och // utför heltalsdelning eller våningsdelning och returnerar golvet för kvoten som ett heltal.

I Python 2 (och de flesta andra programmeringsspråk), såvida inget uttryckligen begärts, utförde x/y heltalsdelning , vilket returnerade en float endast om någon av indata var en float. Men eftersom Python är ett dynamiskt typat språk, var det inte alltid möjligt att avgöra vilken operation som utfördes, vilket ofta ledde till subtila buggar, vilket ledde till introduktionen av //-operatorn och förändringen i semantiken för / -operatorn i Python 3.

Jämförelseoperatörer

Jämförelseoperatorerna, dvs == , != , < , > , <= , >= , är , är inte , in och inte i används på alla möjliga värden. Siffror, strängar, sekvenser och mappningar kan alla jämföras. I Python 3 har olika typer (som en str och en int ) inte en konsekvent relativ ordning. Även om det var möjligt att jämföra om en sträng var större än eller mindre än något heltal i Python 2, ansågs detta vara en historisk designquirk och togs till slut bort i Python 3.

Kedjade jämförelseuttryck som a < b < c har ungefär samma betydelse som de har i matematik, snarare än den ovanliga betydelsen som finns i C och liknande språk. Villkoren utvärderas och jämförs i ordning. Operationen har kortslutningssemantik , vilket innebär att utvärderingen garanterat upphör så snart en dom är klar: om a < b är falskt utvärderas c aldrig eftersom uttrycket omöjligt kan vara sant längre.

För uttryck utan biverkningar är a < b < c ekvivalent med a < b och b < c . Det är dock en väsentlig skillnad när uttrycken har biverkningar. a < f(x) < b kommer att utvärdera f(x) exakt en gång, medan a < f(x) och f(x) < b kommer att utvärdera det två gånger om värdet på a är mindre än f(x) och en gång annars .

Logiska operatorer

00 I alla versioner av Python behandlar booleska operatorer nollvärden eller tomma värden som "" , , None , 0.0 , [] och {} som falskt, medan de i allmänhet behandlar icke-tomma, icke-nollvärden som sanna. De booleska värdena True och False lades till språket i Python 2.2.1 som konstanter (underklassade från 1 och ) och ändrades till att vara fullständiga nyckelord i Python 3. De binära jämförelseoperatorerna som == och > returnerar antingen True eller Falskt .

De booleska operatorerna och och eller använder minimal utvärdering . Till exempel y == 0 eller x/y > 100 aldrig att höja ett dividera-med-noll-undantag. Dessa operatorer returnerar värdet för den senast utvärderade operanden, snarare än True eller False . Sålunda evalueras uttrycket (4 och 5) till 5 och (4 eller 5) evalueras till 4 .

Funktionell programmering

Som nämnts ovan är en annan styrka med Python tillgången till en funktionell programmeringsstil . Som man kan förvänta sig gör detta arbetet med listor och andra samlingar mycket enklare.

Förståelser

En sådan konstruktion är listförståelsen , som kan uttryckas med följande format:

         L  =  [  mapping_expression  för  element  i  källlistan  om  filter_expression  ] 

Använda listförståelse för att beräkna de första fem potenserna av två:

        powers_of_two  =  [  2  **  n  för  n  i  intervallet  (  1  ,  6  )] 

Quicksort - algoritmen kan uttryckas elegant (om än ineffektivt) med hjälp av listuppfattningar:

 
       
         
      0
              
             
                     def  qsort  (  L  ):  om  L  ==  []:  returnera  []  pivot  =  L  [  ]  return  (  qsort  ([  x  för  x  i  L  [  1  :]  om  x  <  pivot  ])  +  [  pivot  ]  +  qsort  ([  x  för  x  i  L  [  1  :]  om  x  >=  pivot  ])) 

Python 2.7+ stöder också uppsättningsförståelser och ordboksförståelser.

Förstklassiga funktioner

I Python är funktioner förstklassiga objekt som kan skapas och skickas runt dynamiskt.

Pythons begränsade stöd för anonyma funktioner är lambda- konstruktionen. Ett exempel är den anonyma funktionen som kvadrerar sin inmatning, anropad med argumentet 5:

    
 f  =  lambda  x  :  x  **  2  f  (  5  ) 

Lambdas är begränsade till att innehålla ett uttryck snarare än påståenden , även om kontrollflödet fortfarande kan implementeras mindre elegant inom lambda genom att använda kortslutning och mer idiomatiskt med villkorliga uttryck.

Stängningar

Python har haft stöd för lexikaliska stängningar sedan version 2.2. Här är en exempelfunktion som returnerar en funktion som approximerar derivatan av den givna funktionen:

  
    


     
               
     def  derivata  (  f  ,  dx  ): """Returnera en funktion som   approximerar  derivatan av f  med hjälp av ett intervall på dx, som bör vara lämpligt litet. """  def  funktion  (  x  ):  return  (  f  (  x  +  dx  )  -  f  (  x  )  )  /  dx  returfunktion  

Pythons syntax leder dock ibland till att programmerare av andra språk tror att nedläggningar inte stöds. Variabelt omfattning i Python bestäms implicit av omfattningen där man tilldelar ett värde till variabeln, såvida inte omfattningen uttryckligen deklareras med global eller icke-lokal .

Observera att stängningens bindning av ett namn till något värde inte kan ändras inifrån funktionen. Given:

  
    
    
     
          
        
    
    

 



 >>>  def  foo  (  a  ,  b  ):  ...  print  (  f  'a:  {  a  }  '  )  ...  print  (  f  'b:  {  b  }  '  )  ...  def  bar  (  c  ):  .. .  b  =  c  ...  print  (  f  'b*:  {  b  }  '  )  ...  bar  (  a  )  ...  print  (  f  'b:  {  b  }  '  )  ...  >>>  foo  (  1  ,  2  )  a: 1  b: 2  b*: 1  b: 2 

och du kan se att b , som syns från stängningens omfattning, behåller det värde den hade; den förändrade bindningen av b inuti den inre funktionen fortplantade sig inte ut. Vägen runt detta är att använda en icke-lokal b -sats i bar . I Python 2 (som saknar icke-lokal ) är den vanliga lösningen att använda ett föränderligt värde och ändra det värdet, inte bindningen. T.ex. en lista med ett element.

Generatorer

Introducerade i Python 2.2 som en valfri funktion och färdigställda i version 2.3, är generatorer Pythons mekanism för lat utvärdering av en funktion som annars skulle returnera en utrymmeskrävande eller beräkningsintensiv lista.

Detta är ett exempel för att lätta generera primtal:

   

 
      
       
                
             
          
           
                
                  
                
                 
                
          
            
              från  itertools  import  count  def  gener_primes  (  stop_at  =  None  ):  primtal  =  []  för  n  i  count  (  start  =  2  ):  om  stop_at  inte  är  None  och  n  >  stop_at  :  return  # höjer StopIteration undantaget  composite  =  False  för  p  i  primtal  :  om  inte  n  %  p  :  sammansatt  =  Sann  brytning  elif  p  **  2  >  n  :  brytning  om  inte  sammansatt  :  primtal  .  lägga till  (  n  )  ge  n 

När du anropar den här funktionen kan det returnerade värdet itereras över ungefär som en lista:

     
    

     
     för  i  i  generera_primtal  (  100  ):  # iterera över primtal mellan 0 och 100  skriv ut  (  i  )  för  i  i  generera_primtal (   ):  # iterera över ALLA primtal på obestämd tid  skriv ut  (  i  ) 

Definitionen av en generator verkar identisk med den för en funktion, förutom att nyckelordet avkastning används i stället för avkastning . En generator är dock ett objekt med beständigt tillstånd, som upprepade gånger kan komma in i och lämna samma omfång. Ett generatoranrop kan sedan användas i stället för en lista eller annan struktur vars element kommer att itereras över. När for- slingan i exemplet kräver nästa objekt, anropas generatorn och ger nästa objekt.

Generatorer behöver inte vara oändliga som exemplet med primtal ovan. När en generator avslutas uppstår ett internt undantag som indikerar för alla anropskontexter att det inte finns fler värden. En for- loop eller annan iteration kommer då att avslutas.

Generatoruttryck

Generatoruttryck, som introducerades i Python 2.4, är den lata utvärderingens motsvarighet till listförståelse. Med hjälp av primtalsgeneratorn i avsnittet ovan kan vi definiera en lat, men inte helt oändlig samling.

   

          
     från  itertools  importera  islice  primes_under_million  =  (  i  för  i  i  gener_primes  ()  om  i  <  1000000  )  two_thousandth_prime  =  islice  (  primes_under_million  ,  1999  ,  2000  )  .  nästa  () 

Det mesta av minnet och tiden som behövs för att generera så många primtal kommer inte att användas förrän det nödvändiga elementet faktiskt har nåtts. Tyvärr kan du inte utföra enkel indexering och skivning av generatorer, utan måste använda itertools -modulen eller "rulla dina egna" loopar. Däremot är en listförståelse funktionellt likvärdig, men är girig när det gäller att utföra allt arbete:

          
   primes_under_million  =  [  i  för  i  i  generera_primtal  (  2000000  )  om  jag  <  1000000  ]  two_thousandth_prime  =  primes_under_million  [  1999  ] 

Listförståelsen kommer omedelbart att skapa en stor lista (med 78498 objekt, i exemplet, men tillfälligt skapa en lista med primtal under två miljoner), även om de flesta element aldrig nås. Generatorförståelsen är mer sparsam.

Ordbok och uppsättningsförståelser

Medan listor och generatorer hade uppfattningar/uttryck, måste i Python-versioner äldre än 2.7 de andra inbyggda Python-samlingstyperna (dikt och uppsättningar) klumpas in i att använda listor eller generatorer:

      
0 0         >>>  dict  ((  n  ,  n  *  n  )  för  n  i  intervallet  (  5  ))  {  :  ,  1  :  1  ,  2  :  4  ,  3  :  9  ,  4  :  16  } 

Python 2.7 och 3.0 förenade alla samlingstyper genom att introducera ordbok och uppsättningsförståelser, liknande listförståelser:

       
0    

       
0    

        
0 0         >>>  [  n  *  n  för  n  i  intervallet  (  5  )]  # vanlig listförståelse  [  ,  1  ,  4  ,  9  ,  16  ]  >>>  >>>  {  n  *  n  för  n  i  intervallet  (  5  )}  # set förståelse  {  ,  1  ,  4  ,  9  ,  16  }  >>>  >>>  {  n  :  n  *  n  för  n  i  intervallet  (  5  )}  # diktförståelse  {  :  ,  1  :  1  ,  2  :  4  ,  3  :  9  ,  4  :  16  } 

Föremål

Python stöder de flesta objektorienterade programmeringstekniker (OOP). Det tillåter polymorfism , inte bara inom en klasshierarki utan också genom att skriva . Vilket objekt som helst kan användas för alla typer, och det kommer att fungera så länge det har rätt metoder och attribut. Och allt i Python är ett objekt, inklusive klasser, funktioner, siffror och moduler. Python har också stöd för metaklasser , ett avancerat verktyg för att förbättra klassernas funktionalitet. Naturligtvis stöds arv , inklusive multipelt arv . Python har mycket begränsat stöd för privata variabler som använder namnmangling som sällan används i praktiken eftersom informationsdöljning av vissa ses som opytoniskt , eftersom det antyder att klassen i fråga innehåller oestetiska eller dåligt planerade interna delar. Sloganen "vi är alla ansvarsfulla användare här" används för att beskriva denna attityd.

Som är sant för moduler, sätter inte klasser i Python en absolut barriär mellan definition och användare, utan förlitar sig snarare på användarens artighet att inte "bryta sig in i definitionen."

9. Klasser , The Python 2.6 Tutorial (2013)

OOP -doktriner som användningen av accessormetoder för att läsa datamedlemmar tillämpas inte i Python. Precis som Python erbjuder funktionella programmeringskonstruktioner men inte försöker kräva referenstransparens , erbjuder den ett objektsystem men kräver inte OOP- beteende. Dessutom är det alltid möjligt att omdefiniera klassen med hjälp av egenskaper (se Egenskaper ) så att när en viss variabel ställs in eller hämtas i anropskod, anropar den verkligen ett funktionsanrop, så att spam.eggs = toast verkligen kan anropa spam.set_eggs (toast) . Detta upphäver den praktiska fördelen med accessorfunktioner, och det förblir OOP eftersom egenskapsäggen blir en legitim del av objektets gränssnitt: det behöver inte återspegla en implementeringsdetalj .

I version 2.2 av Python introducerades "ny stil"-klasser. Med klasser i ny stil förenades objekt och typer, vilket möjliggjorde underklassificering av typer. Även helt nya typer kan definieras, komplett med anpassat beteende för infix-operatörer. Detta gör att många radikala saker kan göras syntaktisk inom Python. En ny metodupplösningsordning för multipelt arv antogs också med Python 2.3. Det är också möjligt att köra anpassad kod medan du använder eller ställer in attribut, även om detaljerna i dessa tekniker har utvecklats mellan Python-versionerna.

Med uttalande

With - satsen hanterar resurser och tillåter användare att arbeta med Context Manager-protokollet. En funktion ( __enter__() ) anropas när man går in i scope och en annan ( __exit__() ) när man lämnar. Detta förhindrar att man glömmer att frigöra resursen och hanterar även mer komplicerade situationer som att frigöra resursen när ett undantag inträffar medan den används. Kontexthanterare används ofta med filer, databasanslutningar, testfall etc.

Egenskaper

Egenskaper tillåter att speciellt definierade metoder anropas på en objektinstans genom att använda samma syntax som används för attributåtkomst. Ett exempel på en klass som definierar vissa egenskaper är:

 
     
          

    
     
         

      
      
           klass  MyClass  :  def  __init__  (  själv  ):  själv  .  _a  =  Ingen  @property  def  a  (  själv  ):  returnera  själv  .  _a  @a  .  setter  # gör egenskapen skrivbar  def  a  (  self  ,  value  ):  self  .  _a  =  värde 

Beskrivningar

En klass som definierar en eller flera av de tre specialmetoderna __get__(själv, instans, ägare) , __set__(self, instans, värde) , __delete__(self, instans) kan användas som en deskriptor. Att skapa en instans av en deskriptor som en klassmedlem i en andra klass gör instansen till en egenskap hos den andra klassen.

Klassiska och statiska metoder

Python tillåter skapandet av klassmetoder och statiska metoder med hjälp av dekoratorerna @classmethod och @staticmethod . Det första argumentet till en klassmetod är klassobjektet istället för självreferensen till instansen. En statisk metod har inget speciellt första argument. Varken instansen eller klassobjektet skickas till en statisk metod.

Undantag

Python stöder (och använder i stor utsträckning) undantagshantering som ett sätt att testa för feltillstånd och andra "exceptionella" händelser i ett program.

Python-stil kräver användning av undantag närhelst ett feltillstånd kan uppstå. Istället för att testa för åtkomst till en fil eller resurs innan den faktiskt används, är det vanligt i Python att bara gå vidare och försöka använda den och fånga undantaget om åtkomst avvisas.

Undantag kan också användas som ett mer allmänt sätt för icke-lokal överföring av kontroll, även när ett fel inte är aktuellt. Mailman- programvaran för e-postlistor, skriven i Python, använder till exempel undantag för att hoppa ur djupt inkapslad logik för meddelandehantering när ett beslut har fattats att avvisa ett meddelande eller hålla det för moderatorgodkännande.

Undantag används ofta som ett alternativ till if -blocket, speciellt i gängade situationer. Ett vanligt motto är EAFP, eller "Det är lättare att be om förlåtelse än tillåtelse", som tillskrivs Grace Hopper . Alternativet, känt som LBYL, eller "Look Before You Leap", testar uttryckligen för förutsättningar.

I detta första kodexempel, efter LBYL-metoden, finns det en explicit kontroll av attributet före åtkomst:

  
      

     om  hasattr  (  skräppost  ,  'ägg'  ):  ham  =  skräppost  .  ägg  annat  :  handle_missing_attr  () 

Detta andra exempel följer EAFP-paradigmet:


      
 
     försök  :  ham  =  skräppost  .  ägg  utom  AttributeError  :  handle_missing_attr  () 

Dessa två kodexempel har samma effekt, även om det kommer att finnas prestandaskillnader. När spam har attributet eggs kommer EAFP-provet att köras snabbare. När spam inte har attributet eggs (det "exceptionella" fallet), kommer EAFP-provet att gå långsammare. Python- profileraren kan användas i specifika fall för att bestämma prestandaegenskaper. Om exceptionella fall är sällsynta kommer EAFP-versionen att ha överlägsen genomsnittlig prestanda än alternativet. Dessutom undviker den hela klassen av TOCTTOU-sårbarheter ( time-of-check-to-time-of-use), andra rasförhållanden och är kompatibel med duck typing . En nackdel med EAFP är att den endast kan användas med uttalanden; ett undantag kan inte fångas i ett generatoruttryck, listförståelse eller lambdafunktion.

Kommentarer och docstrings

Python har två sätt att kommentera Python-kod. En är genom att använda kommentarer för att indikera vad någon del av koden gör. Enradskommentarer börjar med hash-tecknet ( # ) och fortsätter till slutet av raden. Kommentarer som sträcker sig över mer än en rad uppnås genom att infoga en flerradssträng (med """ eller "'" som avgränsare i varje ände) som inte används i tilldelningen eller på annat sätt utvärderas, men som sitter mellan andra påståenden.

Kommentera en kodbit:

 

 
        import  sys  def  getline  ():  return  sys  .  stdin  .  readline  ()  # Få en rad och returnera den 

Kommentera en kod med flera rader:

 
         

 def  getline  ():  return  sys  .  stdin  .  readline  ()  """denna funktion  får en rad  och returnerar den""" 

Docstrings (dokumentationssträngar), det vill säga strängar som är placerade ensamma utan tilldelning som den första indragna raden inom en modul, klass, metod eller funktion, ställer automatiskt in sitt innehåll som ett attribut med namnet __doc__ , som är avsett att lagra en läsbar för människor beskrivning av objektets syfte, beteende och användning. Den inbyggda hjälpfunktionen genererar sin utdata baserat på __doc__- attribut. Sådana strängar kan avgränsas med " eller ' för enradiga strängar, eller kan sträcka sig över flera rader om de avgränsas med antingen """ eller ' '' som är Pythons notation för att specificera flerradiga strängar. Men stilguiden för språket anger att tredubbla citattecken ( """ ) är att föredra för både enkel- och flerradiga docstrings.

Enrads docstring:

 
    
      def  getline  ():  """Hämta en rad från stdin och returnera den."""  return  sys  .  stdin  .  läsrad  () 

Flerrads docstring:

 
    



      def  getline  ():  """Hämta en rad  från stdin  och returnera den. ""  "  return  sys  .  stdin  .  läsrad  () 

Docstrings kan vara så stora som programmeraren vill och innehålla radbrytningar . Till skillnad från kommentarer är docstrings i sig Python-objekt och är en del av den tolkade koden som Python kör. Det betyder att ett program som körs kan hämta sina egna docstrings och manipulera den informationen, men den normala användningen är att ge andra programmerare information om hur man anropar objektet som dokumenteras i docstringen.

Det finns tillgängliga verktyg som kan extrahera docstrings från Python-kod och generera dokumentation. Docstring-dokumentation kan också nås från tolken med hjälp() -funktionen, eller från skalet med pydoc -kommandot pydoc .

Standardmodulen doctest använder interaktioner som kopierats från Python-skalsessioner till docstrings för att skapa tester, medan docopt -modulen använder dem för att definiera kommandoradsalternativ.

Funktionskommentarer

Funktionskommentarer (typtips) definieras i PEP 3107. De tillåter att bifoga data till argumenten och returnera en funktion. Anteckningarnas beteende definieras inte av språket och överlåts till tredje parts ramverk. Till exempel kan ett bibliotek skrivas för att hantera statisk typning:

       def  haul  (  artikel  :  Haulable  ,  *  vargs  :  PackAnimal  )  ->  Avstånd 

Dekoratörer

En dekoratör är alla anropsbara Python-objekt som används för att modifiera en funktion, metod eller klassdefinition. En dekoratör passerar det ursprungliga objektet som definieras och returnerar ett modifierat objekt, som sedan binds till namnet i definitionen. Python-dekoratörer inspirerades delvis av Java-anteckningar och har en liknande syntax; dekorationssyntaxen är rent syntaktisk socker , med @ som nyckelord:


 
     @viking_chorus  def  menu_item  ():  print  (  "spam"  ) 

är ekvivalent med

 
    
   def  menu_item  ():  print  (  "spam"  )  menu_item  =  viking_chorus  (  menu_item  ) 

Dekoratörer är en form av metaprogrammering ; de förstärker verkan av funktionen eller metoden de dekorerar. Till exempel, i exemplet nedan, viking_chorus göra att menu_item körs 8 gånger (se Spam-skiss ) för varje gång det anropas:

 
      
           
             
      def  viking_chorus  (  myfunc  ):  def  inner_func  (  *  args  ,  **  kwargs  ):  för  i  i  intervallet  (  8  ):  myfunc  (  *  args  ,  **  kwargs  )  returnera  inner_func 

Kanoniska användningar av funktionsdekoratorer är för att skapa klassmetoder eller statiska metoder , lägga till funktionsattribut, spåra , ställa in för- och eftervillkor och synkronisering , men kan användas för mycket mer, inklusive eliminering av svansrekursion , memoisering och till och med förbättra skrivningen av andra dekoratörer.

Dekoratörer kan kedjas genom att placera flera på intilliggande linjer:



 
     @invincible  @favourite_colour  (  "Blå"  )  def  black_knight  ():  pass 

är ekvivalent med

 
    
   def  black_knight  ():  pass  black_knight  =  oövervinnerlig  (  favoritfärg  (  "Blå"  )(  black_knight )   ) 

eller med hjälp av mellanliggande variabler

 
    
  
  
   def  black_knight  ():  pass  blue_decorator  =  favourite_colour  (  "Blue"  )  decorated_by_blue  =  blue_decorator  (  black_knight  )  black_knight  =  oövervinnerlig  (  decorated_by_blue  ) 

I exemplet ovan tar favourite_colour dekoratörsfabriken ett argument . Dekoratörsfabriker måste returnera en dekoratör, som sedan anropas med föremålet som ska dekoreras som argument:

 
     
         
            
            
         
      def  favourite_colour  (  color  ):  def  decorator  (  func  ):  def  wrapper  ():  print  (  color  )  func  ()  returnera  wrapper  return  decorator 

Detta skulle sedan dekorera black_knight- funktionen så att färgen, "Blå" , skulle skrivas ut innan black_knight -funktionen körs. Stängning säkerställer att färgargumentet är tillgängligt för den innersta omslagsfunktionen även när den returneras och går utom räckvidd, vilket är det som gör att dekoratörer kan arbeta.

Trots namnet är Python-dekoratörer inte en implementering av dekorationsmönstret . Dekorationsmönstret är ett designmönster som används i statiskt skrivna objektorienterade programmeringsspråk för att tillåta funktionalitet att läggas till objekt under körning; Python-dekoratörer lägger till funktionalitet till funktioner och metoder vid definitionstidpunkten och är därför en konstruktion på högre nivå än klasser av dekoratörsmönster. Själva dekorationsmönstret är trivialt implementerbart i Python, eftersom språket är ducktypat och därför vanligtvis inte betraktas som sådant. [ förtydligande behövs ]

påskägg

Användare av språk med parenteser , som C eller Java , förväntar sig eller önskar ibland att Python följer en blockavgränsningskonvention. Klammeravgränsad blocksyntax har upprepade gånger begärts och konsekvent avvisats av kärnutvecklare. Python-tolken innehåller ett påskägg som sammanfattar utvecklarnas känslor i denna fråga. Koden från __future__ import parentes höjer undantaget SyntaxError: not a chance . Modulen __future__ används normalt för att tillhandahålla funktioner från framtida versioner av Python.

Ett annat dolt meddelande, Zen of Python (en sammanfattning av Pythons designfilosofi ), visas när du försöker importera detta .

Meddelandet Hej världen! skrivs ut när importsatsen import __hello__ används. I Python 2.7, istället för Hello world! det trycker Hello world... .

Genom att importera antigravitationsmodulen öppnas en webbläsare till xkcd comic 353 som skildrar en humoristisk fiktiv användning av en sådan modul, avsedd att demonstrera hur lätt Python-modulerna möjliggör ytterligare funktionalitet. I Python 3 innehåller denna modul även en implementering av "geohash"-algoritmen, en referens till xkcd comic 426 .

externa länkar