Syntaxe a sémantika Pythonu - Python syntax and semantics

Syntax z programovacího jazyka Python je soubor pravidel, která určuje, jak bude program Python písemné a interpretovány (jak v runtime systému a lidské čtenáře). Jazyk Python má mnoho podobností s jazyky Perl , C a Java . Mezi jazyky však existují určité jednoznačné rozdíly.

Filozofie designu

Python byl navržen tak, aby byl vysoce čitelným jazykem. Má relativně přehledné vizuální rozložení a používá anglická klíčová slova často tam, kde jiné jazyky používají interpunkci . Python si klade za cíl být jednoduchý a konzistentní v návrhu své syntaxe, zapouzdřené v mantře „Měl by existovat jeden - a pokud možno pouze jeden - zjevný způsob, jak to udělat“, ze zenu v Pythonu .

Tato mantra se záměrně staví proti mantře Perl a Ruby , „ existuje více než jeden způsob, jak to udělat “.

Klíčová slova

Python má 35 klíčových slov nebo vyhrazených slov ; nemohou být použity jako identifikátory .

  • and
  • as
  • assert
  • async
  • await
  • break
  • class
  • continue
  • def
  • del
  • elif
  • else
  • except
  • False
  • finally
  • for
  • from
  • global
  • if
  • import
  • in
  • is
  • lambda
  • None
  • nonlocal
  • not
  • or
  • pass
  • raise
  • return
  • True
  • try
  • while
  • with
  • yield
Poznámky

Odsazení

Python používá mezery k oddělení bloků toku řízení (podle pravidla off-side ). Python si tuto funkci půjčuje od svého předchůdce ABC : místo interpunkce nebo klíčových slov používá k označení běhu bloku odsazení .

V takzvané „volné formátu“ jazyky-, které používají blokovou strukturu odvozenou od ALGOL -blocks kódu jsou nastaveny off se šlemi ( { }) nebo klíčových slov. Ve většině konvencí kódování pro tyto jazyky programátoři konvenčně odsazují kód v bloku, aby jej vizuálně odlišili od okolního kódu.

Rekurzivní funkce s názvem foo, který je předán jediný parametr , xa pokud je parametr 0 zavolá jinou funkci s názvem bara jinak bude volat baz, prochází x, a také volat sebe rekurzivně, předávání x-1jako parametr, by mohly být realizovány jako je to v jazyce Python :

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

a mohl by být napsán takto v C se stylem odsazení K&R :

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

Python nařizuje konvenci, kterou programátoři v jazycích stylu ALGOL často dodržují.

Nesprávně odsazený kód může být lidským čtenářem přečten jinak, než by byl interpretován překladačem nebo překladačem. Tento příklad ilustruje chybu zavedenou nesprávným odsazením:

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

Zde, na rozdíl od výše uvedeného foopříkladu, je volání funkce foo(x - 1)na posledním řádku chybně odsazeno mimo blok if/ else. To by způsobilo, že bude vždy spuštěno, i když xje 0, což má za následek nekonečnou rekurzi .

Zatímco mezery a znaky tabulátoru jsou přijímány jako formy odsazení a lze použít libovolný násobek mezer, doporučují se mezery a doporučují se 4 mezery (jako v tomto článku), které jsou zdaleka nejčastěji používané. Míchání mezer a tabulátorů na po sobě jdoucích řádcích ve stejném souboru zdrojového kódu není od Pythonu 3 povoleno, protože to může vytvářet chyby, které jsou obtížně viditelné, protože mnoho nástrojů vizuálně nerozlišuje mezery a karty.

Datové struktury

Jelikož je Python dynamicky psaným jazykem , nesou informace o typu hodnoty Pythonu , nikoli proměnné. To má důsledky pro mnoho aspektů fungování jazyka.

Všechny proměnné v Pythonu obsahují odkazy na objekty a tyto odkazy jsou předávány funkcím; funkce nemůže změnit hodnotu odkazů na proměnné ve své volající funkci (ale výjimky viz níže). Někteří lidé (včetně samotného Guida van Rosse ) nazvali toto schéma předávání parametrů „volání podle odkazu na objekt“. Odkaz na objekt znamená jméno a předaný odkaz je „alias“, tj. Kopie odkazu na stejný objekt, stejně jako v C/ C ++ . Hodnotu objektu lze ve volané funkci změnit pomocí „aliasu“, například:

>>> alist = ['a', 'b', 'c']
>>> def my_func(al):
...     al.append('x')
...     print(al)
...
>>> my_func(alist)
['a', 'b', 'c', 'x']
>>> alist
['a', 'b', 'c', 'x']

Funkce my_funczměnila hodnotu alists formálním argumentem al, což je alias alist. Jakýkoli pokus o provozování samotného aliasu však nebude mít na původní objekt žádný vliv. V Pythonu jsou všechny nejniternější-místní a ne-deklarované-globální přístupné názvy aliasy.

Mezi jazyky s dynamickým typem je Python mírně kontrolován. Implicitní převod je definován pro číselných typů (i booleans ), tak jeden může platně násobit komplexní číslo pomocí celé číslo (například) bez explicitního lití. Neexistuje však implicitní převod například mezi čísly a řetězci ; řetězec je neplatný argument pro matematickou funkci, která očekává číslo.

Základní typy

Python má širokou škálu základních datových typů. Vedle konvenční celé řady a aritmetiky s pohyblivou řádovou čárkou transparentně podporuje aritmetiku s libovolnou přesností , komplexní čísla a desetinná čísla .

Python podporuje širokou škálu řetězcových operací. Řetězce v Pythonu jsou neměnné , takže řetězcová operace, jako je náhrada znaků , která v jiných programovacích jazycích může změnit zavedený řetězec , vrátí nový řetězec v Pythonu. Úvahy o výkonu někdy tlačí na používání speciálních technik v programech, které intenzivně upravují řetězce, jako je například spojování polí znaků do řetězců pouze podle potřeby.

Typy sbírek

Jedním z velmi užitečných aspektů Pythonu je koncept typů kolekce (nebo kontejneru ) . Obecně je kolekce objektem, který obsahuje jiné objekty způsobem, na který lze snadno odkazovat nebo jej indexovat . Sbírky se dodávají ve dvou základních formách: sekvence a mapování .

Řazené sekvenční typy jsou seznamy (dynamická pole ), řazené kolekce členů a řetězce. Všechny sekvence jsou indexovány pozičně ( 0 až délka - 1 ) a všechny řetězce kromě mohou obsahovat jakýkoli typ objektu, včetně více typů ve stejné sekvenci. Řetězce i řazené kolekce členů jsou neměnné, což z nich činí perfektní kandidáty na klíče slovníku (viz níže). Seznamy jsou naopak proměnlivé; prvky lze vkládat, mazat, upravovat, připojovat nebo třídit na místě .

Mapování jsou naopak (často neuspořádané) typy implementované ve formě slovníků, které „mapují“ sadu neměnných klíčů na odpovídající prvky (podobně jako matematická funkce). Dalo by se například definovat slovník mající řetězec "toast"mapovaný na celé číslo 42nebo naopak. Klíče ve slovníku musí být neměnného typu Pythonu, například celé číslo nebo řetězec, protože pod pokličkou jsou implementovány pomocí hashovací funkce . To umožňuje mnohem rychlejší dobu vyhledávání, ale vyžaduje, aby se klíče neměnily.

Slovníky jsou ústředním prvkem interních prvků Pythonu, protože jsou umístěny v jádru všech objektů a tříd: mapování mezi názvy proměnných (řetězce) a hodnotami, na které názvy odkazují, jsou uloženy jako slovníky (viz Systém objektů ). Protože jsou tyto slovníky přímo přístupné (prostřednictvím __dict__atributu objektu ), je metaprogramování v Pythonu přímočarým a přirozeným procesem.

Set typ kolekce je neindexovaných, neuspořádané kolekce, která neobsahuje žádné duplikáty, a provádí nastavení teoretické operace, jako je sjednocení , průnik , rozdíl , symetrický rozdíl , a podmnožina testování. Existují dva typy sad: seta frozensetjediným rozdílem je to, že setje proměnlivý a frozensetje neměnný. Prvky v sadě musí být hašovatelné. Například a frozensetmůže být prvkem pravidelnosti, setzatímco opak není pravdou.

Python také poskytuje rozsáhlé schopnosti manipulace se sběrem, jako je integrovaná kontrola kontejnmentu a generický iterační protokol.

Objektový systém

V Pythonu je všechno objekt, dokonce i třídy. Třídy jako objekty mají třídu, která je známá jako jejich metaclass . Python také podporuje vícenásobnou dědičnost a mixiny .

Jazyk podporuje rozsáhlou introspekci typů a tříd. Typy lze číst a porovnávat - typy jsou instance type. Atributy objektu lze extrahovat jako slovník.

Operátory lze v Pythonu přetížit definováním speciálních členských funkcí - například definování metody pojmenované __add__ve třídě umožňuje použití +operátoru na objektech této třídy.

Literály

Řetězce

Python má různé druhy řetězcových literálů .

Normální řetězcové literály

K uvozovkám řetězců lze použít jednoduché nebo dvojité uvozovky. Na rozdíl od jazyků Unix shell, jazyky ovlivněné jazykem Perl nebo Perl, jako jsou Ruby nebo Groovy , jednoduché uvozovky a dvojité uvozovky fungují identicky, tj. Neexistuje žádná interpolace řetězců výrazů $ foo . Interpolaci však lze provést různými způsoby: pomocí „f-řetězců“ (od Pythonu 3.6) pomocí formatmetody nebo starého operátoru % string-format.

Například prohlášení Perl:

print "I just printed $num pages to the printer $printer\n"

je ekvivalentní kterémukoli z těchto příkazů Pythonu:

print(f"I just printed {num} pages to the printer {printer}")

print("I just printed {} pages to the printer {}".format(num, printer))
print("I just printed {0} pages to the printer {1}".format(num, printer))
print("I just printed {num} pages to the printer {printer}".format(num=num, printer=printer))

print("I just printed %s pages to the printer %s" % (num, printer))
print("I just printed %(num)s pages to the printer %(printer)s" % {"num": num, "printer": printer})

Víceřádkové řetězcové literály

Existují také víceřádkové řetězce, které začínají a končí řadou tří jednoduchých nebo dvojitých uvozovek a fungují jako zde dokumenty v jazycích Perl a Ruby .

Jednoduchý příklad s variabilní interpolací (pomocí formatmetody) je:

print("""Dear {recipient},

I wish you to leave Sunnydale and never return.

Not Quite Love,
{sender}
""".format(sender="Buffy the Vampire Slayer", recipient="Spike"))

Surové struny

Nakonec všechny dříve zmíněné typy řetězců přicházejí v „ surových “ variantách (označených umístěním doslovného r před úvodní uvozovku), které neprovádějí interpolaci zpětného lomítka, a proto jsou velmi užitečné pro regulární výrazy ; porovnat "@-citování" v C# . Původní řetězce byly původně zahrnuty speciálně pro regulární výrazy. Kvůli omezením tokenizeru nemusí mít surové řetězce koncové zpětné lomítko. Vytvoření nezpracovaného řetězce, který obsahuje cestu systému Windows končící zpětným lomítkem, vyžaduje určité řešení (obvykle použití lomítek místo zpětných lomítek, protože systém Windows přijímá obojí).

Mezi příklady patří:

>>> # A Windows path, even raw strings cannot end in a backslash
>>> r"C:\Foo\Bar\Baz\"
  File "<stdin>", line 1
    r"C:\Foo\Bar\Baz\"
                     ^
SyntaxError: EOL while scanning string literal

>>> dos_path = r"C:\Foo\Bar\Baz\ " # avoids the error by adding
>>> dos_path.rstrip()              # and removing trailing space
'C:\\Foo\\Bar\\Baz\\'

>>> quoted_dos_path = r'"{}"'.format(dos_path)
>>> quoted_dos_path
'"C:\\Foo\\Bar\\Baz\\ "'

>>> # A regular expression matching a quoted string with possible backslash quoting
>>> re.match(r'"(([^"\\]|\\.)*)"', quoted_dos_path).group(1).rstrip()
'C:\\Foo\\Bar\\Baz\\'

>>> code = 'foo(2, bar)'
>>> # Reverse the arguments in a two-arg function call
>>> re.sub(r'\(([^,]*?),([^ ,]*?)\)', r'(\2, \1)', code)
'foo(2, bar)'
>>> # Note that this won't work if either argument has parens or commas in it.

Zřetězení sousedních řetězcových literálů

Řetězcové literály (s použitím případně jiných konvencí uvozovek), které se objevují souvisle a oddělené pouze mezerami (včetně nových řádků), jsou povoleny a jsou agregovány do jednoho delšího řetězce. Tím pádem

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

je ekvivalentní

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

Unicode

Od Pythonu 3.0 je výchozí znaková sada UTF-8 jak pro zdrojový kód, tak pro tlumočníka. V UTF-8 jsou řetězce unicode zpracovávány jako tradiční bajtové řetězce. Tento příklad bude fungovat:

s = "Γειά" # Hello in Greek
print(s)

Čísla

Numerické literály v Pythonu jsou normální druhu, například 0, -1, 3.4, 3.5e-8.

Python má celá čísla libovolné délky a automaticky zvyšuje velikost úložiště podle potřeby. Před Pythonem 3 existovaly dva druhy integrálních čísel: tradiční celá čísla s pevnou velikostí a „dlouhá“ celá čísla libovolné velikosti. Konverze na „dlouhá“ celá čísla byla v případě potřeby provedena automaticky, a programátor si tedy obvykle nemusel být vědom dvou integrálních typů. V novějších jazykových verzích je rozdíl úplně pryč a všechna celá čísla se chovají jako celá čísla libovolné délky.

Python podporuje normální čísla s plovoucí desetinnou čárkou , která se vytvářejí, když je tečka použita v doslovném smyslu (např. 1.1), Když je ve výrazu použito celé číslo a číslo s plovoucí desetinnou čárkou, nebo jako výsledek některých matematických operací („skutečné dělení“ pomocí /operátor, nebo umocňování s negativním exponent).

Python také nativně podporuje komplexní čísla . Složitá čísla jsou označena příponou Jnebo j, např 3 + 4j.

Seznamy, řazené kolekce členů, sady, slovníky

Python má syntaktickou podporu pro vytváření typů kontejnerů.

Seznamy (třída list) jsou proměnlivé sekvence položek libovolných typů a lze je vytvořit buď pomocí speciální syntaxe

a_list = [1, 2, 3, "a dog"]

nebo pomocí normálního vytváření objektů

a_second_list = list()
a_second_list.append(4)
a_second_list.append(5)

Tuple (třída tuple) jsou neměnné sekvence položek libovolných typů. Existuje také speciální syntaxe pro vytváření n -tic

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

Ačkoli jsou n -tice vytvářeny oddělením položek čárkami, celá konstrukce je obvykle za účelem zvýšení čitelnosti zabalena do závorek. Prázdná n -tice je označena ().

Sady (třída set) jsou měnitelné kontejnery hashovatelných položek libovolných typů, bez duplikátů. Položky nejsou objednány, ale sady podporují opakování položek. Syntaxe pro vytváření sady používá složené závorky

some_set = {0, (), False}

Sady Pythonu jsou velmi podobné matematickým sadám a podporují operace, jako je protnutí sady a sjednocení . Python také nabízí frozensettřídu pro neměnné sady, viz Typy kolekcí .

Slovníky (třída dict) jsou proměnlivá mapování, která spojují klíče a odpovídající hodnoty. Python má speciální syntaxi pro vytváření slovníků ( {key: value})

a_dictionary = {"key 1": "value 1", 2: 3, 4: []}

Syntaxe slovníku je podobná nastavené syntaxi, rozdílem je přítomnost dvojteček. Prázdné doslovné {}vede spíše než prázdné slovník prázdné množiny, který je místo toho vytvořen pomocí non-doslovný konstruktor: set().

Operátoři

Aritmetický

Python zahrnuje +, -, *, /( "true dělení"), //( podlaha Division) %( modul ) a **( umocňování ) operátory, se svým obvyklým matematickým přednosti .

V Pythonu 3 x / yprovádí „skutečné dělení“, což znamená, že vždy vrací float, i když oba xa yjsou celá čísla, která se dělí rovnoměrně.

>>> 4 / 2
2.0

a //provede celočíselné dělení nebo dělení podlaží , přičemž vrací dno kvocientu jako celé číslo.

V Pythonu 2 (a ve většině ostatních programovacích jazyků), pokud to nebylo výslovně požadováno, x / yprovedlo celočíselné dělení a vrátilo float pouze v případě, že jeden ze vstupů byl float. Protože je však Python dynamicky psaný jazyk, nebylo vždy možné zjistit, která operace byla prováděna, což často vedlo k jemným chybám, což vedlo k zavedení //operátoru a změně sémantiky /operátoru v Pythonu 3.

Srovnávací operátoři

Operátorů porovnání, tedy ==, !=, <, >, <=, >=, is, is not, ina not injsou používány na všech možných hodnot. Lze porovnávat čísla, řetězce, sekvence a mapování. V Pythonu 3 nesourodé typy (například a stra an int) nemají konzistentní relativní řazení. I když bylo možné porovnat, zda byl některý řetězec větší než nebo menší než nějaké celé číslo v Pythonu 2, toto bylo považováno za historický designový vtípek a nakonec bylo v Pythonu 3 odstraněno.

Zřetězené srovnávací výrazy, jako například, a < b < cmají zhruba význam, který mají v matematice, spíše než neobvyklý význam v C a podobných jazycích. Podmínky jsou vyhodnoceny a porovnány v pořadí. Operace má sémantiku zkratu , což znamená, že vyhodnocení se zaručeně zastaví, jakmile bude jasný verdikt: pokud a < bje nepravdivý, cnikdy se nevyhodnocuje, protože výraz již pravděpodobně nemůže být pravdivý.

Pro výrazy bez vedlejších účinků a < b < cje ekvivalentní a < b and b < c. Existuje však podstatný rozdíl, pokud mají výrazy vedlejší účinky. a < f(x) < bvyhodnotí f(x)přesně jednou, zatímco a < f(x) and f(x) < bvyhodnotí dvakrát, pokud je hodnota amenší než f(x)a jednou jinak.

Logické operátory

Ve všech verzích Pythonu, logické operátory jednat nulové hodnoty nebo prázdné hodnoty, například "", 0, None, 0.0, []a {}jako nepravdivé, zatímco obecně léčení non-prázdné, nenulové hodnoty jako pravda. Booleovské hodnoty Truea Falsebyly přidány do jazyka v Pythonu 2.2.1 jako konstanty (podtřídy od 1a 0) a byly změněny tak, aby byly plně rozvinutými klíčovými slovy v Pythonu 3. Binární srovnávací operátory jako ==a >vrátí buď Truenebo False.

Booleovské operátory anda orpoužívají minimální hodnocení . Například y == 0 or x/y > 100nikdy nevyvolá výjimku dělení nulou. Tito operátoři vracejí hodnotu posledního vyhodnoceného operandu namísto Truenebo False. Výraz tedy (4 and 5)vyhodnotí 5a (4 or 5)vyhodnotí 4.

Funkcionální programování

Jak bylo uvedeno výše, další silnou stránkou Pythonu je dostupnost funkčního programovacího stylu. Jak lze očekávat, díky tomu je práce se seznamy a dalšími kolekcemi mnohem jednodušší.

Porozumění

Jednou takovou konstrukcí je porozumění seznamu , které lze vyjádřit v následujícím formátu:

L = [mapping_expression for element in source_list if filter_expression]

Pomocí porozumění seznamu pro výpočet prvních pěti mocnin ze dvou:

powers_of_two = [2**n for n in range(1, 6)]

Quicksort algoritmus může být vyjádřen elegantně (byť neefektivně) s použitím list comprehension:

def qsort(L):
    if L == []:
        return []
    pivot = L[0]
    return (qsort([x for x in L[1:] if x < pivot]) +
            [pivot] +
            qsort([x for x in L[1:] if x >= pivot]))

Python 2.7+ také podporuje porozumění množinám a porozumění slovníku.

Prvotřídní funkce

V Pythonu jsou funkce prvotřídními objekty, které lze vytvářet a předávat dynamicky.

Python je omezená podpora pro anonymní funkce je lambdakonstrukt. Příkladem je anonymní funkce, která kvadrátuje její vstup, volaná s argumentem 5:

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

Lambdy jsou omezeny na to, aby obsahovaly výraz spíše než příkazy , ačkoli řídicí tok může být stále implementován méně elegantně v lambda pomocí zkratování a více idiomaticky s podmíněnými výrazy.

Uzávěry

Python má podporu pro lexikální uzávěry od verze 2.2. Zde je příklad funkce, která vrací funkci, která aproximuje derivaci dané funkce:

def derivative(f, dx):
    """Return a function that approximates the derivative of f
    using an interval of dx, which should be appropriately small.
    """
    def function(x):
        return (f(x + dx) - f(x)) / dx
    return function

Syntaxe Pythonu však někdy vede programátory jiných jazyků k názoru, že zavírání není podporováno. Rozsah proměnné v Pythonu je implicitně určen oborem, ve kterém je proměnné přiřazena hodnota, pokud není rozsah výslovně deklarován pomocí globalnebo nonlocal.

Všimněte si, že vazba uzavření jména na nějakou hodnotu není z funkce měnitelná. Vzhledem k:

>>> 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

a můžete vidět, že b, jak je vidět z rozsahu uzávěru, si zachovává hodnotu, kterou měl; změněná vazba buvnitř vnitřní funkce se nešířila ven. Cesta kolem toho je použít nonlocal bpříkaz v bar. V Pythonu 2 (který chybí nonlocal) je obvyklým řešením použít proměnnou hodnotu a změnit tuto hodnotu, nikoli vazbu. Např. Seznam s jedním prvkem.

Generátory

Představené v Pythonu 2.2 jako volitelná funkce a dokončené ve verzi 2.3, generátory jsou mechanismem Pythonu pro líné vyhodnocení funkce, která by jinak vrátila seznam omezující prostor nebo výpočetně náročný seznam.

Toto je příklad líného generování prvočísel:

from itertools import count

def generate_primes(stop_at=None):
    primes = []
    for n in count(start=2):
        if stop_at is not None and n > stop_at:
            return # raises the StopIteration exception
        composite = False
        for p in primes:
            if not n % p:
                composite = True
                break
            elif p ** 2 > n:
                break
        if not composite:
            primes.append(n)
            yield n

Při volání této funkce lze vrácenou hodnotu iterovat podobně jako seznam:

for i in generate_primes(100):  # iterate over the primes between 0 and 100
    print(i)

for i in generate_primes():  # iterate over ALL primes indefinitely
    print(i)

Definice generátoru se zdá být identická s definicí funkce, kromě toho, že yieldmísto něj je použito klíčové slovo return. Generátor je však objekt s trvalým stavem, který může opakovaně vstupovat a opouštět stejný rozsah. Volání generátoru pak lze použít místo seznamu nebo jiné struktury, jejíž prvky budou iterovány. Kdykoli forsmyčka v příkladu vyžaduje další položku, je vyvolán generátor a získá další položku.

Generátory nemusí být nekonečné jako výše uvedený příklad prvočísla. Když generátor skončí, vyvolá se interní výjimka, která pro jakýkoli kontext volání znamená, že neexistují žádné další hodnoty. forSmyčky nebo jiné iterace se poté ukončí.

Výrazy generátoru

Generátorové výrazy představené v Pythonu 2.4 jsou líným ekvivalentem hodnocení porozumění seznamu. Pomocí generátoru prvočísel uvedeného ve výše uvedené části bychom mohli definovat línou, ale ne zcela nekonečnou kolekci.

from itertools import islice

primes_under_million = (i for i in generate_primes() if i < 1000000)
two_thousandth_prime = islice(primes_under_million, 1999, 2000).next()

Většina paměti a času potřebného k vygenerování tohoto počtu prvočísel nebude použita, dokud se k potřebnému prvku skutečně nedostane. Jednoduché indexování a krájení generátorů bohužel nemůžete provádět, ale musíte použít modul itertools nebo smyčky „roll your own“. Naproti tomu porozumění seznamu je funkčně ekvivalentní, ale při provádění všech prací je chamtivé :

primes_under_million = [i for i in generate_primes(2000000) if i < 1000000]
two_thousandth_prime = primes_under_million[1999]

Porozumění seznamu okamžitě vytvoří rozsáhlý seznam (v tomto případě 78498 položek, ale přechodně vytvoří seznam prvočísel pod dva miliony), i když k většině prvků se nikdy nedostane. Porozumění generátoru je šetrnější.

Slovník a porozumění množinám

Zatímco seznamy a generátory měly porozumění/výrazy, ve verzích Pythonu starších než 2,7 musely být jiné vestavěné typy kolekcí (dikty a sady) v Pythonu utlumeny pomocí seznamů nebo generátorů:

>>> dict((n, n*n) for n in range(5))
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Python 2.7 a 3.0 sjednotil všechny typy kolekcí zavedením porozumění slovníku a množiny, podobně jako porozumění seznamu:

>>> [n*n for n in range(5)]  # regular list comprehension
[0, 1, 4, 9, 16]
>>>
>>> {n*n for n in range(5)}  # set comprehension
{0, 1, 4, 9, 16}
>>>
>>> {n: n*n for n in range(5)}  # dict comprehension
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Objekty

Python podporuje většinu technik objektově orientovaného programování (OOP). Umožňuje polymorfismus , a to nejen v rámci třídní hierarchie, ale také pomocí psaní kachen . Jakýkoli objekt lze použít pro jakýkoli typ a bude fungovat, pokud má správné metody a atributy. A vše v Pythonu je objekt, včetně tříd, funkcí, čísel a modulů. Python také podporuje metaklasy , pokročilý nástroj pro vylepšení funkcí tříd. Přirozeně je podporována dědičnost , včetně vícenásobné dědičnosti . Python má velmi omezenou podporu pro soukromé proměnné pomocí manipulace s názvy, která se v praxi používá jen zřídka, protože skrývání informací je některými vnímáno jako nepytonické , protože naznačuje, že daná třída obsahuje neestetické nebo špatně naplánované interní prvky. K popisu tohoto postoje se používá slogan „tady jsme všichni zodpovědní uživatelé“.

Jak to platí pro moduly, třídy v Pythonu nekladou absolutní bariéru mezi definicí a uživatelem, ale spoléhají na slušnost uživatele, aby „neprorazil do definice“.

-  9. Classes , The Python 2.6 Tutorial (2013)

Doktríny OOP , jako je použití přístupových metod ke čtení datových členů, nejsou v Pythonu vynucovány. Stejně jako Python nabízí konstrukty funkčního programování, ale nepokouší se požadovat referenční transparentnost , nabízí objektový systém, ale nevyžaduje chování OOP . Kromě toho je vždy možné předefinovat třídu pomocí vlastností (viz Vlastnosti ), takže když je určitá proměnná nastavena nebo načtena ve volacím kódu, skutečně vyvolá volání funkce, takže se spam.eggs = toastmůže skutečně vyvolat spam.set_eggs(toast). To ruší praktickou výhodu funkcí přístupového objektu a zůstává OOP, protože vlastnost se eggsstává legitimní součástí rozhraní objektu: nemusí odrážet detail implementace.

Ve verzi 2.2 Pythonu byly zavedeny třídy „nového stylu“. S třídami nového stylu byly objekty a typy sjednoceny, což umožnilo podtřídy typů. Lze definovat i zcela nové typy, doplněné o vlastní chování operátorů infixů. To umožňuje mnoho radikálních věcí dělat v Pythonu syntakticky. V Pythonu 2.3 bylo také přijato nové pořadí rozlišení metody pro vícenásobnou dědičnost. Je také možné spouštět vlastní kód při přístupu nebo nastavování atributů, i když se podrobnosti o těchto technikách mezi verzemi Pythonu vyvinuly.

S prohlášením

Příkaz withzpracovává prostředky a umožňuje uživatelům pracovat s protokolem Context Manager. Jedna funkce ( __enter__()) je volána při zadávání rozsahu a další ( __exit__()) při opouštění. Tím se zabrání zapomenutí uvolnit zdroj a také se řeší složitější situace, jako je uvolnění zdroje, když dojde k výjimce, když se používá. Správci kontextu se často používají se soubory, databázovými připojeními, testovacími případy atd.

Vlastnosti

Vlastnosti umožňují vyvolání speciálně definovaných metod na instanci objektu pomocí stejné syntaxe, jaká byla použita pro přístup k atributům. Příkladem třídy definující některé vlastnosti je:

class MyClass:
    def __init__(self):
        self._a = None

    @property
    def a(self):
        return self._a

    @a.setter  # makes the property writable
    def a(self, value):
        self._a = value

Deskriptory

Třída, která definuje jeden nebo více ze tří speciálních metod __get__(self, instance, owner), __set__(self, instance, value), __delete__(self, instance)může být použit jako deskriptor. Vytvoření instance deskriptoru jako člena třídy druhé třídy činí z instance vlastnost druhé třídy.

Třída a statické metody

Python umožňuje vytváření třídních metod a statických metod pomocí dekorátorů@classmethod a . Prvním argumentem pro metodu třídy je objekt třídy místo vlastního odkazu na instanci. Statická metoda nemá žádný speciální první argument. Ani instance, ani objekt třídy nejsou předány statické metodě. @staticmethod

Výjimky

Python podporuje (a široce využívá) zpracování výjimek jako prostředek testování chybových stavů a ​​dalších „výjimečných“ událostí v programu. Ve skutečnosti je dokonce možné zachytit výjimku způsobenou chybou syntaxe .

Styl Python vyžaduje použití výjimek, kdykoli může dojít k chybové situaci. Spíše než testovat přístup k souboru nebo zdroji před jeho skutečným použitím je v Pythonu obvyklé jednoduše pokračovat a pokusit se jej použít, přičemž zachytí výjimku, pokud je přístup odmítnut.

Výjimky lze také použít jako obecnější prostředek nelokálního přenosu řízení, i když se nejedná o chybu. Například software Mailman list, napsaný v Pythonu, používá výjimky k vyskočení z hluboce vnořené logiky zpracování zpráv, když bylo učiněno rozhodnutí odmítnout zprávu nebo ji podržet pro schválení moderátorem.

Výjimky se často používají jako alternativa k if-bloku, zvláště v situacích s vlákny . Běžně používaným mottem je EAFP neboli „Je snazší požádat o odpuštění než o povolení“, které je přisuzováno Grace Hopperové . Alternativa, známá jako LBYL nebo „Look Before You Leap“, výslovně testuje předběžné podmínky.

V této první ukázce kódu po přístupu LBYL existuje explicitní kontrola atributu před přístupem:

if hasattr(spam, 'eggs'):
    ham = spam.eggs
else:
    handle_missing_attr()

Tento druhý vzorek se řídí paradigmatem EAFP:

try:
    ham = spam.eggs
except AttributeError:
    handle_missing_attr()

Tyto dva ukázky kódu mají stejný účinek, i když budou rozdíly ve výkonu. Pokud spammá atribut eggs, ukázka EAFP poběží rychleji. Pokud spamnemá atribut eggs(„výjimečný“ případ), ukázka EAFP poběží pomaleji. Profilátor Pythonu lze v konkrétních případech použít k určení charakteristik výkonu. Pokud jsou výjimečné případy výjimečné, bude mít verze EAFP vynikající průměrný výkon než alternativa. Kromě toho se vyhýbá celé třídě zranitelností od doby kontroly do doby použití (TOCTTOU) a dalším rasovým podmínkám a je kompatibilní s psaním kachen . Nevýhodou EAFP je, že jej lze použít pouze s příkazy; výjimku nelze zachytit ve výrazu generátoru, porozumění seznamu nebo funkci lambda.

Komentáře a dokumenty

Python má dva způsoby, jak anotovat kód Pythonu. Jedním z nich je pomocí komentářů určit, co která část kódu dělá. Jednořádkové komentáře začínají znakem hash ( #) a pokračují až do konce řádku. Komentářů zahrnujících více než jeden řádek je dosaženo vložením víceřádkového řetězce (s """nebo '''jako oddělovač na každém konci), který není použit v přiřazení nebo jinak vyhodnocen, ale sedí mezi jinými příkazy.

Komentování kousku kódu:

import sys

def getline():
    return sys.stdin.readline()  # Get one line and return it

Komentování části kódu několika řádky:

def getline():
    return sys.stdin.readline()    """this function
                                      gets one line
                                      and returns it"""

Docstrings (řetězce dokumentace), tj. Řetězce, které jsou umístěny samostatně bez přiřazení jako první odsazený řádek v modulu, třídě, metodě nebo funkci, automaticky nastaví jejich obsah jako pojmenovaný atribut __doc__, který je určen k uložení popisu čitelného pro člověka účelu, chování a použití objektu. Vestavěná helpfunkce generuje svůj výstup na základě __doc__atributů. Takové řetězce mohou být odděleny s "nebo 'pro jednořádkové řetězce, nebo mohou zahrnovat více řádků, pokud jsou odděleny buď jedním """nebo '''který je zápisem Pythonu pro určení víceřádkových řetězců. Průvodce stylem pro jazyk však uvádí, že """pro jednořádkové i víceřádkové dokumenty jsou upřednostňovány trojité uvozovky ( ).

Jednořádkový dokumentový řetězec:

def getline():
    """Get one line from stdin and return it."""
    return sys.stdin.readline()

Víceřádkový dokumentový řetězec:

def getline():
    """Get one line
       from stdin
       and return it.
    """
    return sys.stdin.readline()

Dokumenty mohou být tak velké, jak si programátor přeje, a mohou obsahovat konce řádků . Na rozdíl od komentářů jsou docstrings samy objekty Pythonu a jsou součástí interpretovaného kódu, který Python spouští. To znamená, že běžící program může načíst své vlastní dokumenty a manipulovat s těmito informacemi, ale normálním způsobem je poskytnout ostatním programátorům informace o tom, jak vyvolat objekt dokumentovaný v řetězci dokumentů.

K dispozici jsou nástroje, které mohou extrahovat řetězce dokumentů z kódu Pythonu a generovat dokumentaci. K dokumentaci Docstring lze také přistupovat z tlumočníka s help()funkcí nebo z prostředí shell pomocí příkazu pydocpydoc .

Modul doctest standard používá k vytváření testů interakce zkopírované z relací prostředí Python do docstrings , zatímco modul docopt je používá k definování možností příkazového řádku.

Anotace funkcí

Popisy funkcí (rady typů) jsou definovány v PEP 3107. Umožňují připojení dat k argumentům a návrat funkce. Chování anotací není definováno jazykem a je ponecháno na rámcích třetích stran. Knihovnu lze například zapsat pro zpracování statického psaní:

def haul(item: Haulable, *vargs: PackAnimal) -> Distance

Dekoratéři

Dekorátor je libovolný objekt Python, který lze volat, který se používá k úpravě definice funkce, metody nebo třídy. Dekorátoru je předán definovaný původní objekt a vrací upravený objekt, který je pak vázán na jméno v definici. Dekorátoři Pythonu se částečně inspirovali anotacemi Java a mají podobnou syntaxi; syntaxe dekorátoru je čistý syntaktický cukr , @jako klíčové slovo:

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

je ekvivalentní

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

Dekoratéry jsou formou metaprogramování ; posilují působení funkce nebo metody, kterou zdobí. Například v níže uvedeném příkladu viking_chorusmůže způsobit, menu_itemže bude spuštěno 8krát (viz skica spamu ) pro každé volání:

def viking_chorus(myfunc):
    def inner_func(*args, **kwargs):
        for i in range(8):
            myfunc(*args, **kwargs)
    return inner_func

Kanonické použití dekorátorů funkcí je pro vytváření třídních metod nebo statických metod , přidávání atributů funkcí, trasování , nastavení pre- a postkondicionů a synchronizaci , ale lze je použít pro mnohem více, včetně eliminace rekurze ocasu , memoizace a dokonce zlepšení psaní jiných dekoratéři.

Dekoratéry lze zřetězit umístěním několika na sousední řádky:

@invincible
@favourite_colour("Blue")
def black_knight():
    pass

je ekvivalentní

def black_knight():
    pass
black_knight = invincible(favourite_colour("Blue")(black_knight))

nebo pomocí přechodných proměnných

def black_knight():
    pass
blue_decorator = favourite_colour("Blue")
decorated_by_blue = blue_decorator(black_knight)
black_knight = invincible(decorated_by_blue)

Ve výše uvedeném příkladu má továrnafavourite_colour dekoratéra argument. Továrny dekoratéra musí vrátit dekorátora, který je pak volán s předmětem, který má být ozdoben, jako jeho argument:

def favourite_colour(colour):
    def decorator(func):
        def wrapper():
            print(colour)
            func()
        return wrapper
    return decorator

Tím by se black_knightfunkce ozdobila tak, že by se barva, "Blue"vytiskla před black_knightspuštěním funkce. Uzavření zajišťuje, že argument barvy je přístupný funkci nejvnitřnější obálky, i když je vrácen a jde mimo rozsah, což umožňuje dekoratérům pracovat.

Navzdory názvu nejsou dekoratéři Pythonu implementací vzoru dekorátoru . Vzor dekorátoru je návrhový vzor používaný ve staticky typovaných objektově orientovaných programovacích jazycích, které umožňují přidávat funkce k objektům za běhu; Dekorátoři Pythonu přidávají funkce a metody v době definice, a jsou tedy konstrukcí vyšší úrovně než třídy vzorů dekorátoru. Samotný vzor dekorátoru je v Pythonu triviálně implementovatelný, protože jazyk je psán kachním písmem , a proto se za něj obvykle nepovažuje.

velikonoční vajíčka

Uživatelé jazyků složených závorek , jako je C nebo Java , někdy očekávají nebo si přejí, aby Python dodržoval konvenci oddělovače bloků. Syntaxe bloku oddělená složenou závorkou byla opakovaně požadována a hlavní vývojáři ji důsledně odmítali. Interpret Pythonu obsahuje velikonoční vajíčko, které shrnuje pocity jeho vývojářů k tomuto problému. Kód from __future__ import bracesvyvolává výjimku SyntaxError: not a chance. __future__Modul se běžně používá k poskytování funkcí z budoucích verzí Pythonu.

Při pokusu se zobrazí další skrytá zpráva, Zen of Python (souhrn filozofie designu Pythonu ) import this.

Zpráva Hello world!se vytiskne při použití příkazu k importu import __hello__. V Pythonu 2.7 místo toho Hello world!tiskne Hello world....

Import antigravitymodulu otevře webový prohlížeč pro xkcd comic 353, který zobrazuje vtipné fiktivní použití takového modulu, jehož cílem je demonstrovat snadnost, s jakou moduly Pythonu umožňují další funkce. V Pythonu 3 tento modul také obsahuje implementaci algoritmu „geohash“, odkaz na xkcd comic 426 .

Reference

externí odkazy