stringtranslate.com

Синтаксис и семантика Python

Фрагмент кода Python с ключевыми словами, выделенными жирным желтым шрифтом

Синтаксис языка программирования Python — это набор правил, определяющих, как программа Python будет написана и интерпретирована (как системой выполнения , так и людьми-читателями). Язык Python во многом похож на Perl , C и Java . Однако между языками есть некоторые определенные различия. Он поддерживает несколько парадигм программирования , включая структурное, объектно-ориентированное и функциональное программирование , а также может похвастаться динамической системой типов и автоматическим управлением памятью.

Синтаксис Python прост и последователен, придерживаясь принципа, что «Должен быть один — и желательно только один — очевидный способ сделать это». Язык включает встроенные типы данных и структуры, механизмы управления потоком, функции первого класса и модули для лучшей возможности повторного использования и организации кода . Python также использует английские ключевые слова там, где другие языки используют знаки препинания, что способствует его лаконичному визуальному оформлению.

Язык обеспечивает надежную обработку ошибок с помощью исключений и включает отладчик в стандартной библиотеке для эффективного решения проблем. Синтаксис Python, разработанный для удобства чтения и простоты использования, делает его популярным выбором как среди новичков, так и среди профессионалов.

Философия дизайна

Python был разработан как легко читаемый язык. [1] Он имеет относительно лаконичную визуальную компоновку и часто использует английские ключевые слова там, где другие языки используют пунктуацию . Python стремится быть простым и последовательным в дизайне своего синтаксиса, заключенного в мантре «Должен быть один — и желательно только один — очевидный способ сделать это», из Дзен Python . [2]

Эта мантра намеренно противопоставляется мантре Perl и Ruby : « Есть больше одного способа сделать это ».

Ключевые слова

В Python есть 35 ключевых слов или зарезервированных слов ; их нельзя использовать в качестве идентификаторов . [3] [4]

Кроме того, в Python также есть 3 мягких ключевых слова . В отличие от обычных жестких ключевых слов , мягкие ключевые слова являются зарезервированными словами только в ограниченных контекстах, где интерпретация их как ключевых слов имела бы синтаксический смысл. Эти слова могут использоваться как идентификаторы в других местах, другими словами, match и case являются допустимыми именами для функций и переменных. [6] [7]

Примечания
  1. ^ ab asyncи awaitбыли введены в Python 3.5. [5]
  2. ^ ab Trueи Falseстали ключевыми словами в Python 3.0. Ранее они были глобальными переменными .
  3. ^ nonlocal был представлен в Python 3.0.
  4. ^ abc matchи были введены caseкак _ключевые слова в Python 3.10.

Отступ

Python использует пробелы для разграничения блоков потока управления (следуя правилу «вне игры »). Python заимствует эту функцию у своего предшественника ABC : вместо знаков препинания или ключевых слов он использует отступы для обозначения последовательности блоков .

В так называемых языках "свободного формата" — которые используют блочную структуру, полученную из ALGOL — блоки кода выделяются фигурными скобками ( { }) или ключевыми словами. В большинстве соглашений о кодировании для этих языков программисты традиционно делают отступы в коде внутри блока, чтобы визуально отделить его от окружающего кода.

Рекурсивная функция с именем , которой передается один параметр , и если параметр равен 0, вызовет другую функцию с именем , в противном случае вызовет , передав , а также рекурсивно вызовет саму себя, передав в качестве параметра, может быть реализована на Python следующим образом:fooxbarbazxx-1

def  foo ( x ):  если  x  ==  0 :  bar ()  иначе :  baz ( x )  foo ( x  -  1 )

и может быть записано следующим образом на языке C с использованием стиля отступа K&R :

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

Неправильно отступленный код может быть неправильно прочитан человеком-читателем иначе, чем он будет интерпретирован компилятором или интерпретатором. Например, если вызов функции foo(x - 1)в последней строке в примере выше был ошибочно отступлен за пределами блока if/ else:

def  foo ( x ):  если  x  ==  0 :  bar ()  иначе :  baz ( x )  foo ( x  -  1 )

это приведет к тому, что последняя строка будет выполняться всегда, даже если xона равна 0, что приведет к бесконечной рекурсии .

Хотя в качестве форм отступа принимаются как пробелы , так и символы табуляции , и можно использовать любое кратное им количество пробелов, рекомендуется использовать пробелы [8] , а 4 пробела (как в приведенных выше примерах) рекомендуются и используются чаще всего. [9] [10] [ ненадежный источник? ] Начиная с Python 3, смешивание пробелов и табуляции в последовательных строках не допускается [11], поскольку это может привести к ошибкам, которые трудно заметить, поскольку многие текстовые редакторы визуально не различают пробелы и табуляции.

Структуры данных

Поскольку Python — язык с динамической типизацией , информацию о типе несут значения Python, а не переменные . Все переменные в Python содержат ссылки на объекты , и эти ссылки передаются функциям. Некоторые люди (включая самого Гвидо ван Россума ) называли эту схему передачи параметров «вызовом по ссылке на объект». Ссылка на объект означает имя, а переданная ссылка — «псевдоним», т. е. копия ссылки на тот же объект, как в C/ C++ . Значение объекта может быть изменено в вызываемой функции с помощью «псевдонима», например:

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

Функция my_funcизменяет значение alistс помощью формального аргумента al, который является псевдонимом alist. Однако любая попытка работы (назначения новой ссылки на объект) с самим псевдонимом не окажет никакого влияния на исходный объект. [ требуется пояснение ]

>>> alist  =  [ 'a' ,  'b' ,  'c' ] >>> def  my_func ( al ): ...  # al.append('x') ...  al  =  al  +  [ 'x' ]  # новый список создан и назначен al, значит al больше не является псевдонимом для alist ...  print ( al ) ... >>> my_func ( alist ) ['a', 'b', 'c', 'x'] >>> print ( alist ) ['a', 'b', 'c']

В Python нелокальные внутренние и необъявленные глобальные доступные имена являются псевдонимами.

Среди динамически типизированных языков Python умеренно типизирован. Неявное преобразование определено для числовых типов (а также булевых ), поэтому можно допустимо умножить комплексное число на целое число (например) без явного приведения . Однако неявного преобразования, например, между числами и строками нет ; строка является недопустимым аргументом для математической функции, ожидающей число.

Базовые типы

Python имеет широкий спектр базовых типов данных. Наряду с обычной целочисленной и плавающей арифметикой, он прозрачно поддерживает арифметику произвольной точности , комплексные числа и десятичные числа .

Python поддерживает широкий спектр строковых операций. Строки в Python неизменяемы , поэтому строковая операция, такая как замена символов , которая в других языках программирования может изменить строку на месте , возвращает новую строку в Python. Соображения производительности иногда подталкивают к использованию специальных методов в программах, которые интенсивно изменяют строки, например, объединение массивов символов в строки только по мере необходимости.

Типы коллекций

Одним из очень полезных аспектов Python является концепция типов коллекций (или контейнеров ). В общем случае коллекция — это объект, содержащий другие объекты таким образом, что на него легко ссылаться или индексировать . Коллекции бывают двух основных форм: последовательности и отображения .

Упорядоченные последовательные типы — это списки (динамические массивы ), кортежи и строки. Все последовательности индексируются позиционно ( от 0 до длины - 1 ), и все, кроме строк, могут содержать любой тип объекта, включая несколько типов в одной и той же последовательности. И строки, и кортежи являются неизменяемыми, что делает их идеальными кандидатами на роль ключей словаря (см. ниже). С другой стороны, списки изменяемы; элементы можно вставлять, удалять, изменять, добавлять или сортировать на месте .

С другой стороны, отображения (часто неупорядоченные) — это типы, реализованные в виде словарей , которые «сопоставляют» набор неизменяемых ключей с соответствующими элементами (подобно математической функции). Например, можно определить словарь, имеющий строку, "toast"сопоставленную с целым числом 42, или наоборот. Ключи в словаре должны быть неизменяемого типа Python, например, целым числом или строкой, поскольку под капотом они реализованы с помощью хэш-функции . Это значительно ускоряет время поиска, но требует, чтобы ключи не менялись.

Словари играют центральную роль во внутренних компонентах Python, поскольку они находятся в основе всех объектов и классов: сопоставления между именами переменных (строками) и значениями, на которые ссылаются имена, хранятся в виде словарей (см. Система объектов). Поскольку эти словари доступны напрямую (через __dict__атрибут объекта), метапрограммирование является простым и естественным процессом в Python.

Тип коллекции множеств — это неиндексированная, неупорядоченная коллекция, которая не содержит дубликатов и реализует операции теории множеств , такие как объединение , пересечение , разность , симметричная разность и проверка подмножеств . Существует два типа множеств: setи frozenset, единственное отличие в том, что setявляется изменяемым и frozensetявляется неизменяемым. Элементы в множестве должны быть хешируемыми. Таким образом, например, a frozensetможет быть элементом регулярного , setтогда как обратное неверно.

Python также предоставляет обширные возможности манипулирования коллекциями, такие как встроенная проверка включений и универсальный протокол итерации.

Система объектов

В Python все является объектом, даже классы. Классы, как объекты, имеют класс, который известен как их метакласс . Python также поддерживает множественное наследование и миксины .

Язык поддерживает обширную интроспекцию типов и классов. Типы можно читать и сравнивать — типы являются экземплярами type. Атрибуты объекта можно извлечь как словарь.

Операторы в Python можно перегружать , определяя специальные функции-члены — например, определение метода, названного __add__в классе, позволяет использовать +оператор в объектах этого класса.

Литералы

Струны

В Python есть различные виды строковых литералов .

Обычные строковые литералы

Для кавычек строк можно использовать как одинарные, так и двойные кавычки. В отличие от языков оболочки Unix, Perl или языков, находящихся под влиянием Perl, таких как Ruby или Groovy , одинарные и двойные кавычки работают одинаково, т. е. интерполяция строк выражений $foo отсутствует . Однако интерполяция может быть выполнена различными способами: с помощью "f-strings" (начиная с Python 3.6 [12] ), с использованием formatметода или старого оператора форматирования строк % .

Например, все эти операторы Python:

print ( f "Я только что распечатал { num } страниц на принтере { printer } " )print ( "Я только что распечатал {} страниц на принтере {} " . format ( num ,  printer )) print ( "Я только что распечатал {0} страниц на принтере {1} " . format ( num ,  printer )) print ( "Я только что распечатал {num} страниц на принтере {printer} " . format ( num = num ,  printer = printer ))print ( "Я только что распечатал %s страниц на принтере %s "  %  ( num ,  printer )) print ( "Я только что распечатал %(num)s страниц на принтере %(printer)s "  %  { "num" :  num ,  "printer" :  printer })

эквивалентны оператору Perl:

print "Я только что распечатал $num страниц на принтере $printer\n" 

Они создают строку, используя переменные numи printer.

Многострочные строковые литералы

Существуют также многострочные строки, которые начинаются и заканчиваются серией из трех одинарных или двойных кавычек и функционируют подобно документам в Perl и Ruby .

Простой пример с интерполяцией переменных (с использованием formatметода):

print ( '''Уважаемый {получатель} ,Я желаю тебе покинуть Саннидейл и никогда не возвращаться.Не совсем любовь, {отправитель} ''' . формат ( отправитель = "Баффи - истребительница вампиров" ,  получатель = "Спайк" ))

Необработанные строки

Наконец, все ранее упомянутые типы строк поставляются в « сырых » разновидностях (обозначаемых размещением литерала r перед открывающей кавычкой), которые не делают интерполяции обратной косой черты и, следовательно, очень полезны для регулярных выражений ; сравните «@-цитирование» в C# . Исходно необработанные строки были включены специально для регулярных выражений. Из-за ограничений токенизатора необработанные строки могут не иметь завершающей обратной косой черты. [13] Создание необработанной строки, содержащей путь Windows , заканчивающийся на обратную косую черту, требует некоторого разнообразия обходных путей (обычно с использованием прямой косой черты вместо обратной косой черты, поскольку Windows принимает обе).

Вот несколько примеров:

>>> # Путь Windows, даже необработанные строки, не могут заканчиваться обратной косой чертой >>> r "C:\Foo\Bar\Baz \" Файл "<stdin>" , строка 1 r "C:\Foo\Bar\Baz \" ^ SyntaxError : EOL при сканировании строкового литерала  >>> dos_path  =  r "C:\Foo\Bar\Baz\ "  # избегает ошибки, добавляя >>> dos_path . rstrip ()  # и удаляя завершающий пробел 'C:\\Foo\\Bar\\Baz\\'>>> quote_dos_path  =  r '" {} "' . format ( dos_path ) >>> quote_dos_path '"C:\\Foo\\Bar\\Baz\\ "'>>> # Регулярное выражение, сопоставляющее строку в кавычках с возможным обратным слешем >>> re . match ( r '"(([^" \\ ]| \\ .)*)"' ,  quote_dos_path ) . group ( 1 ) . rstrip () 'C:\\Foo\\Bar\\Baz\\'>>> code  =  'foo(2, bar)' >>> # Поменять местами аргументы в вызове функции с двумя аргументами >>> re . sub ( r '\(([^,]*?),([^ ,]*?)\)' ,  r '(\2, \1)' ,  code ) 'foo(2, bar)' >>> # Обратите внимание, что это не сработает, если в каком-либо из аргументов есть скобки или запятые.

Конкатенация смежных строковых литералов

Строковые литералы (возможно, с использованием различных соглашений о кавычках), появляющиеся подряд и разделенные только пробелами (включая новые строки), допускаются и объединяются в одну длинную строку. [14] Таким образом

title  =  "Один хороший поворот: " \ 'Естественная история отвертки и винта'

эквивалентно

title  =  «Один хороший поворот: естественная история отвертки и винта»

Юникод

Начиная с Python 3.0, кодировка по умолчанию — UTF-8 как для исходного кода, так и для интерпретатора. В UTF-8 строки unicode обрабатываются как традиционные байтовые строки. Этот пример будет работать:

s  =  "Γειά"  # Привет по-гречески печатать ( s )

Числа

Числовые литералы в Python имеют обычный вид, например 0, -1, , 3.4, 3.5e-8.

Python имеет целые числа произвольной длины и автоматически увеличивает размер их хранилища по мере необходимости. До Python 3 существовало два вида целых чисел: традиционные целые числа фиксированного размера и «длинные» целые числа произвольного размера. Преобразование в «длинные» целые числа выполнялось автоматически при необходимости, и поэтому программисту обычно не нужно было знать о двух типах целых чисел. В более новых версиях языка это различие полностью исчезло, и все целые числа ведут себя как целые числа произвольной длины.

Python поддерживает обычные числа с плавающей точкой , которые создаются при использовании точки в литерале (например, 1.1), при использовании в выражении целого числа и числа с плавающей точкой или в результате некоторых математических операций («истинное деление» с помощью оператора /или возведение в степень с отрицательным показателем).

Python также поддерживает комплексные числа изначально. Комплексные числа обозначаются суффиксом Jor j, например 3 + 4j.

Списки, кортежи, множества, словари

В Python имеется синтаксическая поддержка создания типов контейнеров.

Списки (класс list) представляют собой изменяемую последовательность элементов произвольных типов и могут быть созданы либо с помощью специального синтаксиса

a_list  =  [ 1 ,  2 ,  3 ,  "собака" ]

или используя обычное создание объекта

a_second_list  =  [ ] a_second_list.append ( 4 ) a_second_list.append ( 5 )

Кортежи (класс tuple) — это неизменяемые последовательности элементов произвольных типов. Также существует специальный синтаксис для создания кортежей

a_tuple  =  1 ,  2 ,  3 ,  "четыре" a_tuple  =  ( 1 ,  2 ,  3 ,  "четыре" )

Хотя кортежи создаются путем разделения элементов запятыми, вся конструкция обычно заключается в скобки для повышения читабельности. Пустой кортеж обозначается как (), в то время как кортеж с одним значением может быть создан с помощью (1,).

Наборы (класс set) — это изменяемые контейнеры хешируемых элементов [15] произвольных типов, без дубликатов. Элементы не упорядочены, но наборы поддерживают итерацию по элементам. Синтаксис для создания набора использует фигурные скобки

some_set  =  { 0 ,  (),  Ложь }

Множества Python очень похожи на математические множества и поддерживают такие операции, как пересечение и объединение множеств . В Python также есть frozensetкласс для неизменяемых множеств, см. Типы коллекций.

Словари (класс dict) — это изменяемые отображения, связывающие ключи и соответствующие значения. В Python есть специальный синтаксис для создания словарей ( {key: value})

a_dictionary  =  { "ключ 1" :  "значение 1" ,  2 :  3 ,  4 :  []}

Синтаксис словаря похож на синтаксис набора, разница в наличии двоеточий. Пустой литерал {}приводит к пустому словарю, а не пустому набору, который вместо этого создается с помощью нелитерального конструктора: set().

Операторы

Арифметика

В Python есть операторы +, -, *, /(«истинное деление»), //( деление с округлением до нуля ), %( модуль ) и **( возведение в степень ) с их обычным математическим приоритетом .

В Python 3 x / yвыполняет «истинное деление», то есть всегда возвращает число с плавающей точкой, даже если xи yявляются целыми числами, которые делятся нацело.

>>> 4  /  2 2.0

и //выполняет целочисленное деление или деление с уменьшением на 1 , возвращая уменьшение частного в виде целого числа.

В Python 2 (и большинстве других языков программирования), если явно не запрашивалось, x / yвыполнялось целочисленное деление , возвращая float только в том случае, если любой из входных данных был float. Однако, поскольку Python является динамически типизированным языком, не всегда было возможно определить, какая операция выполнялась, что часто приводило к тонким ошибкам, что побудило ввести оператор //и изменить семантику оператора /в Python 3.

Операторы сравнения

Операторы сравнения, то есть ==, !=, <, >, <=, >=, is, is not, inи not in[16], используются для всех видов значений. Числа, строки, последовательности и отображения можно сравнивать. В Python 3 разнородные типы (такие как a strи an int) не имеют последовательного относительного порядка, и попытки сравнить эти типы вызывают TypeErrorисключение. Хотя в Python 2 можно было сравнивать разнородные типы (например, была ли строка больше или меньше целого числа), порядок был неопределенным; это считалось исторической причудой дизайна и в конечном итоге было удалено в Python 3.

Связанные выражения сравнения, такие как a < b < cимеют примерно то же значение, что и в математике, а не необычное значение, которое можно найти в C и подобных языках. Термины оцениваются и сравниваются по порядку. Операция имеет семантику короткого замыкания , что означает, что оценка гарантированно прекратится, как только вердикт станет ясен: если a < bложно, cникогда не оценивается, поскольку выражение больше не может быть истинным.

Для выражений без побочных эффектов a < b < cэквивалентно a < b and b < c. Однако существует существенная разница, когда выражения имеют побочные эффекты. a < f(x) < bбудет вычисляться f(x)ровно один раз, тогда как a < f(x) and f(x) < bбудет вычисляться дважды, если значение aменьше, чем f(x)и один раз в противном случае.

Логические операторы

Во всех версиях Python булевы операторы обрабатывают нулевые значения или пустые значения, такие как "", 0, None, 0.0, [], и {}как ложные, в то время как в целом обрабатывают непустые, ненулевые значения как истинные. Булевы значения Trueи Falseбыли добавлены в язык в Python 2.2.1 как константы (подклассы 1и 0) и были изменены на полноценные ключевые слова в Python 3. Бинарные операторы сравнения, такие как ==и , >возвращают либо Trueили False.

Булевы операторы andи orиспользуют минимальную оценку . Например, y == 0 or x/y > 100никогда не вызовет исключение деления на ноль. Эти операторы возвращают значение последнего вычисленного операнда, а не Trueили False. Таким образом, выражение (4 and 5)вычисляется как 5, а (4 or 5)вычисляется как 4.

Функциональное программирование

Как уже упоминалось выше, еще одной сильной стороной Python является наличие функционального стиля программирования . Как и следовало ожидать, это значительно упрощает работу со списками и другими коллекциями.

Понимания

Одной из таких конструкций является списочное понимание , которое можно выразить в следующем формате:

L  =  [ выражение_отображения  для  элемента  в  исходном_списке ,  если  выражение_фильтра ]

Использование понимания списков для вычисления первых пяти степеней двойки:

powers_of_two  =  [ 2 ** n  для  n  в  диапазоне ( 1 ,  6 )]

Алгоритм быстрой сортировки можно элегантно (хотя и неэффективно) выразить с помощью списковых включений:

def  qsort ( L ):  если  L  ==  []:  return  []  pivot  =  L [ 0 ]  return  ( qsort ([ x  для  x  в  L [ 1 :]  если  x  <  pivot ])  +  [ pivot ]  +  qsort ([ x  для  x  в  L [ 1 :]  если  x  >=  pivot ]))

Python 2.7+ [17] также поддерживает множества [18] и словари [19] .

Первоклассные функции

В Python функции — это объекты первого класса , которые можно создавать и передавать динамически.

Ограниченная поддержка анонимных функций в Python — это lambdaконструкция. Примером может служить анонимная функция, которая возводит в квадрат свой ввод, вызываемая с аргументом 5:

f  =  лямбда  x :  x ** 2 f ( 5 )

Лямбда-выражения ограничены содержанием выражений , а не операторов , хотя поток управления все еще может быть реализован менее элегантно в лямбда-выражениях с помощью короткого замыкания [20] и более идиоматично с помощью условных выражений [21] .

Закрытия

Python поддерживает лексические замыкания с версии 2.2. Вот пример функции, которая возвращает функцию, которая аппроксимирует производную заданной функции:

def  derived ( f ,  dx ): """Возвращает функцию, которая аппроксимирует производную f  с использованием интервала dx, который должен быть достаточно малым.  """ def function ( x ): return ( f ( x + dx ) - f ( x )) / dx return function             

Однако синтаксис Python иногда заставляет программистов других языков думать, что замыкания не поддерживаются. Область действия переменной в Python неявно определяется областью действия, в которой переменной присваивается значение, если только область действия явно не объявлена ​​с помощью globalили nonlocal. [22]

Обратите внимание, что привязка имени к некоторому значению в замыкании не может быть изменена изнутри функции. Дано:

>>> def  foo ( a ,  b ): ...  печать ( f 'a: { a } ' ) ...  печать ( f 'b: { b } ' ) ...  def  bar ( c ): ...  b  =  c ...  печать ( f 'b*: { b } ' ) ...  bar ( a ) ...  печать ( f 'b: { b } ' ) ... >>> foo ( 1 ,  2 ) a: 1 b: 2 b*: 1 b: 2

и вы можете видеть, что b, как видно из области действия замыкания, сохраняет значение, которое у него было; измененная привязка bвнутри внутренней функции не распространилась наружу. Обойти это можно, используя nonlocal bоператор в bar. В Python 2 (где отсутствует nonlocal) обычным решением является использование изменяемого значения и изменение этого значения, а не привязки. Например, список с одним элементом.

Генераторы

Генераторы, представленные в Python 2.2 как дополнительная функция и окончательно доработанные в версии 2.3, представляют собой механизм Python для ленивой оценки функции, которая в противном случае вернула бы список, занимающий слишком много места или требующий больших вычислительных ресурсов.

Это пример ленивой генерации простых чисел:

из  itertools  количество импортов def  generate_primes ( stop_at = None ):  primes  =  []  for  n  in  count ( start = 2 ):  if  stop_at  is  not  None  and  n  >  stop_at :  return  # вызывает исключение StopIteration  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

При вызове этой функции возвращаемое значение можно перебирать подобно списку:

for  i  in  generate_primes ( 100 ):  # перебрать простые числа от 0 до 100  print ( i )for  i  in  generate_primes ():  # перебрать ВСЕ простые числа бесконечно  print ( i )

Определение генератора выглядит идентичным определению функции, за исключением того, что yieldвместо return. Однако генератор — это объект с постоянным состоянием, который может многократно входить и выходить из одной и той же области действия. Вызов генератора затем может использоваться вместо списка или другой структуры, элементы которой будут перебираться. Всякий раз, когда цикл forв примере требует следующий элемент, вызывается генератор и выдает следующий элемент.

Генераторы не обязательно должны быть бесконечными, как в примере с простым числом выше. Когда генератор завершается, возникает внутреннее исключение, которое указывает любому вызывающему контексту, что больше нет значений. forЗатем цикл или другая итерация завершатся.

Генератор выражений

Представленные в Python 2.4, выражения генератора являются эквивалентом ленивой оценки спискового включения. Используя генератор простых чисел, представленный в предыдущем разделе, мы можем определить ленивую, но не совсем бесконечную коллекцию.

из  itertools  импортировать  isliceпростые_числа_меньше_миллиона  =  ( i  для  i  в  generate_primes ()  если  i  <  1000000 ) двухтысячное_простое  =  islice ( простые_числа_меньше_миллиона ,  1999 ,  2000 ) .next ( )

Большая часть памяти и времени, необходимых для генерации стольких простых чисел, не будет использована, пока нужный элемент не будет фактически доступен. К сожалению, вы не можете выполнить простую индексацию и нарезку генераторов, а должны использовать модуль itertools или «свернуть свои собственные» циклы. Напротив, списочное включение функционально эквивалентно, но жадно выполняет всю работу:

простые_числа_меньше_миллиона  =  [ i  для  i  в  generate_primes ( 2000000 )  если  i  <  1000000 ] двухтысячные_простые числа  =  простые_числа_меньше_миллиона [ 1999 ]

Понимание списка немедленно создаст большой список (в примере с 78498 элементами, но временно создаст список простых чисел менее двух миллионов), даже если большинство элементов никогда не будут доступны. Понимание генератора более экономно.

Словарь и множество понятий

В то время как списки и генераторы имели включения/выражения, в версиях Python старше 2.7 другие встроенные типы коллекций Python (dictions и sets) приходилось вставлять с помощью списков или генераторов:

>>>  dict (( n ,  n * n )  для  n  в  диапазоне ( 5 )) { 0 :  0 ,  1 :  1 ,  2 :  4 ,  3 :  9 ,  4 :  16 }

Python 2.7 и 3.0 объединили все типы коллекций, введя генераторы словарей и множеств, аналогичные генераторам списков:

>>>  [ n * n  for  n  in  range ( 5 )]  # обычное включение списка [ 0 ,  1 ,  4 ,  9 ,  16 ] >>> >>>  { n * n  for  n  in  range ( 5 )}  # включение набора { 0 ,  1 ,  4 ,  9 ,  16 } >>> >>>  { n :  n * n  for  n  in  range ( 5 )}  # включение словаря { 0 :  0 ,  1 :  1 ,  2 :  4 ,  3 :  9 ,  4 :  16 }

Объекты

Python поддерживает большинство методов объектно-ориентированного программирования (ООП). Он допускает полиморфизм не только в иерархии классов , но и с помощью утиной типизации . Любой объект может использоваться для любого типа, и он будет работать, пока у него есть соответствующие методы и атрибуты. И все в Python является объектом, включая классы, функции, числа и модули. Python также поддерживает метаклассы , продвинутый инструмент для улучшения функциональности классов. Естественно, поддерживается наследование , включая множественное наследование . Python имеет очень ограниченную поддержку закрытых переменных с использованием искажения имен , которое редко используется на практике, поскольку сокрытие информации рассматривается некоторыми как непитонское , поскольку оно предполагает, что рассматриваемый класс содержит неэстетичные или плохо спланированные внутренние компоненты. Для описания такого отношения используется лозунг «мы все здесь ответственные пользователи». [23]

Как и модули, классы в Python не возводят абсолютный барьер между определением и пользователем, а скорее полагаются на вежливость пользователя, чтобы не «вторгаться в определение».

—  9. Классы, Учебник Python 2.6 (2013)

Доктрины ООП , такие как использование методов доступа для чтения членов данных, не применяются в Python. Так же, как Python предлагает конструкции функционального программирования, но не пытается требовать ссылочной прозрачности , он предлагает объектную систему, но не требует поведения ООП . Более того, всегда можно переопределить класс с помощью свойств (см. Свойства), так что когда определенная переменная устанавливается или извлекается в вызывающем коде, он действительно вызывает вызов функции, так что это spam.eggs = toastдействительно может вызвать spam.set_eggs(toast). Это сводит на нет практическое преимущество функций доступа, и он остается ООП, потому что свойство eggsстановится законной частью интерфейса объекта: оно не должно отражать детали реализации.

В версии 2.2 Python были введены классы «нового стиля». С классами нового стиля объекты и типы были унифицированы, что позволило создавать подклассы типов. Можно определять даже совершенно новые типы, дополненные пользовательским поведением для инфиксных операторов. Это позволяет делать многие радикальные вещи синтаксически в Python. Новый порядок разрешения методов для множественного наследования также был принят в Python 2.3. Также возможно запускать пользовательский код при доступе к атрибутам или их установке, хотя детали этих методов развивались между версиями Python.

С заявлением

Оператор withобрабатывает ресурсы и позволяет пользователям работать с протоколом Context Manager. [24] Одна функция ( __enter__()) вызывается при входе в область действия, а другая ( __exit__()) — при выходе. Это предотвращает забывание освободить ресурс, а также обрабатывает более сложные ситуации, такие как освобождение ресурса при возникновении исключения во время его использования. Context Managers часто используются с файлами, подключениями к базам данных, тестовыми случаями и т. д.

Характеристики

Свойства позволяют вызывать специально определенные методы для экземпляра объекта, используя тот же синтаксис, который используется для доступа к атрибутам. Пример класса, определяющего некоторые свойства:

класс  MyClass :  def  __init__ ( self )  : self._a = None   @property  def  a ( self ):  вернуть  self . _a @a . setter  # делает свойство доступным для записи  def  a ( self ,  value ):  self . _a  =  value

Дескрипторы

Класс, определяющий один или несколько из трех специальных методов __get__(self, instance, owner), __set__(self, instance, value), __delete__(self, instance)может использоваться как дескриптор. Создание экземпляра дескриптора как члена класса второго класса делает экземпляр свойством второго класса. [25]

Класс и статические методы

Python позволяет создавать методы класса и статические методы с помощью декораторов @classmethod и @staticmethod. Первым аргументом метода класса является объект класса, а не ссылка на сам экземпляр. Статический метод не имеет специального первого аргумента. Ни экземпляр, ни объект класса не передаются статическому методу.

Исключения

Python поддерживает (и широко использует) обработку исключений как средство тестирования на наличие ошибок и других «исключительных» событий в программе.

Стиль Python требует использования исключений всякий раз, когда может возникнуть условие ошибки. Вместо того, чтобы проверять доступ к файлу или ресурсу перед его фактическим использованием, в Python принято просто идти вперед и пытаться использовать его, перехватывая исключение, если доступ отклонен.

Исключения также могут использоваться как более общее средство нелокальной передачи управления, даже если ошибка не является проблемой. Например, программное обеспечение для рассылки Mailman , написанное на Python, использует исключения для выхода из глубоко вложенной логики обработки сообщений, когда принято решение отклонить сообщение или удержать его для одобрения модератором.

Исключения часто используются как альтернатива -block if, особенно в потоковых ситуациях. Обычно используемый девиз — EAFP, или «Проще просить прощения, чем разрешения» [26], который приписывается Грейс Хоппер . [27] [28] Альтернатива, известная как LBYL, или «Посмотри, прежде чем прыгнуть», явно проверяет наличие предварительных условий. [29]

В этом первом примере кода, следуя подходу LBYL, есть явная проверка атрибута перед доступом:

если  hasattr ( спам ,  ' яйца ' ):  ham  =  спам . eggs иначе :  handle_missing_attr ()

Второй пример следует парадигме EAFP:

попробуйте :  ham  =  spam . eggs кроме  AttributeError :  handle_missing_attr ()

Эти два примера кода имеют одинаковый эффект, хотя будут различия в производительности. Если spamесть атрибут eggs, образец EAFP будет работать быстрее. Если spamнет атрибута eggs(случай «исключительный»), образец EAFP будет работать медленнее. Профилировщик Python может использоваться в определенных случаях для определения характеристик производительности. Если исключительные случаи редки, то версия EAFP будет иметь более высокую среднюю производительность, чем альтернатива. Кроме того, она избегает целого класса уязвимостей времени проверки до времени использования (TOCTTOU), других состояний гонки [28] [30] и совместима с утиной типизацией . Недостатком EAFP является то, что его можно использовать только с операторами; исключение не может быть перехвачено в выражении генератора, представлении списка или лямбда-функции.

Комментарии и строки документации

В Python есть два способа аннотировать код Python. Один из них — использовать комментарии для указания того, что делает некоторая часть кода. Однострочные комментарии начинаются с символа решетки ( #) и продолжаются до конца строки. Комментарии, охватывающие более одной строки, достигаются путем вставки многострочной строки (с """или '''в качестве разделителя на каждом конце), которая не используется в присваивании или иным образом не оценивается, а находится между другими операторами.

Комментирование фрагмента кода:

импортировать  системуdef  getline ( ) :  return  sys.stdin.readline ( ) # Получить одну строку и вернуть ее 

Комментирование фрагмента кода с несколькими строками:

def  getline (): """Эта функция получает одну строку и возвращает ее.  В качестве демонстрации приведем многострочную строку документации. Доступ к этой полной строке можно получить как getline.__doc__.  """  return  sys . stdin . readline ()

Строки документации (документационные строки), то есть строки, которые располагаются отдельно без назначения в качестве первой отступной строки в модуле, классе, методе или функции, автоматически устанавливают свое содержимое в качестве атрибута с именем __doc__, который предназначен для хранения понятного человеку описания цели, поведения и использования объекта. Встроенная helpфункция генерирует свой вывод на основе __doc__атрибутов. Такие строки могут быть разделены "или 'для однострочных строк, или могут охватывать несколько строк, если разделены """или , '''что является нотацией Python для указания многострочных строк. Однако руководство по стилю для языка указывает, что тройные двойные кавычки ( """) предпочтительны как для однострочных, так и для многострочных строк документации. [31]

Однострочная строка документации:

def  getline (): """Получить одну строку из stdin и вернуть ее.""" return sys . stdin . readline ()   

Многострочная строка документации:

def  getline (): """Получить одну строку  из stdin  и вернуть ее.  """ return sys . stdin . readline ()   

Строки документации могут быть настолько большими, насколько захочет программист, и содержать переносы строк . В отличие от комментариев, строки документации сами по себе являются объектами Python и частью интерпретируемого кода, который выполняет Python. Это означает, что запущенная программа может извлекать свои собственные строки документации и манипулировать этой информацией, но обычно они используются для предоставления другим программистам информации о том, как вызвать объект, документируемый в строке документации.

Существуют инструменты, которые могут извлекать docstrings из кода Python и генерировать документацию. Документацию docstring также можно получить из интерпретатора с помощью help()функции или из оболочки с помощью команды pydocpydoc .

Стандартный модуль doctest использует взаимодействия, скопированные из сеансов оболочки Python в строки документации, для создания тестов, тогда как модуль docopt использует их для определения параметров командной строки.

Аннотации функций

Аннотации функций (подсказки типов) определены в PEP 3107. [32] Они позволяют прикреплять данные к аргументам и возвращать функцию. Поведение аннотаций не определяется языком и остается на усмотрение сторонних фреймворков. Например, можно написать библиотеку для обработки статической типизации: [32]

def  haul ( item :  Haulable ,  * vargs :  PackAnimal )  ->  Расстояние

Декораторы

Декоратор — это любой вызываемый объект Python, который используется для изменения определения функции, метода или класса. Декоратору передается исходный определяемый объект, и он возвращает измененный объект, который затем привязывается к имени в определении. Декораторы Python были частично вдохновлены аннотациями Java и имеют похожий синтаксис; синтаксис декоратора — это чистый синтаксический сахар , использующий @в качестве ключевого слова:

@viking_chorus def  menu_item ():  печать ( "спам" )

эквивалентно

def  menu_item ():  print ( "спам" ) menu_item  =  viking_chorus ( menu_item )

Декораторы — это форма метапрограммирования ; они улучшают действие функции или метода, которые они декорируют. Например, в примере ниже viking_chorusможет menu_itemбыть выполнено 8 раз (см. Spam sketch ) для каждого вызова:

def  viking_chorus ( myfunc ):  def  inner_func ( * args ,  ** kwargs ):  для  i  в  диапазоне ( 8 ):  myfunc ( * args ,  ** kwargs )  return  inner_func

Каноническое использование декораторов функций — создание методов класса или статических методов , добавление атрибутов функций, трассировка , установка предварительных и постусловий и синхронизация [33] , но их можно использовать и для гораздо большего, включая устранение хвостовой рекурсии [34] , мемоизацию и даже улучшение написания других декораторов. [35]

Декораторы можно объединять в цепочку, размещая несколько на соседних строках:

@invincible @favourite_colour ( "Blue" ) def  black_knight ():  пас

эквивалентно

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

или, используя промежуточные переменные

def  black_knight ():  pass blue_decorator  =  favorite_colour ( "Blue" ) decorative_by_blue  =  blue_decorator ( black_knight ) black_knight  =  invincible ( decorative_by_blue )

В приведенном выше примере фабрикаfavourite_colour декораторов принимает аргумент. Фабрики декораторов должны возвращать декоратор, который затем вызывается с декорируемым объектом в качестве аргумента:

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

Это затем декорирует black_knightфункцию таким образом, что цвет, "Blue", будет напечатан до black_knightзапуска функции. Замыкание гарантирует, что аргумент цвета доступен для самой внутренней функции-обертки, даже если он возвращается и выходит из области видимости, что позволяет декораторам работать.

Несмотря на название, декораторы Python не являются реализацией шаблона декоратора . Шаблон декоратора — это шаблон проектирования, используемый в статически типизированных объектно-ориентированных языках программирования , позволяющий добавлять функциональность к объектам во время выполнения; декораторы Python добавляют функциональность к функциям и методам во время определения и, таким образом, являются конструкцией более высокого уровня, чем классы шаблонов декораторов. Сам шаблон декоратора тривиально реализуем в Python, поскольку язык имеет утиную типизацию , и поэтому обычно не рассматривается как таковой. [ требуется пояснение ]

пасхальные яйца

Пользователи языков с фигурными скобками , таких как C или Java , иногда ожидают или желают, чтобы Python следовал соглашению о разделителях блоков. Синтаксис блоков, разделенных фигурными скобками, неоднократно запрашивался и последовательно отвергался основными разработчиками. Интерпретатор Python содержит пасхальное яйцо , которое суммирует чувства его разработчиков по этому вопросу. Код from __future__ import bracesвызывает исключение SyntaxError: not a chance. __future__Модуль обычно используется для предоставления функций из будущих версий Python.

Другое скрытое сообщение, Zen of Python (краткое изложение философии дизайна Python ), отображается при попытке import this.

Сообщение Hello world!выводится при import __hello__использовании оператора импорта. В Python 2.7 вместо Hello world!этого выводится Hello world....

Импорт antigravityмодуля открывает веб-браузер с комиксом xkcd 353, который изображает юмористическое вымышленное использование такого модуля, призванное продемонстрировать легкость, с которой модули Python обеспечивают дополнительную функциональность. [36] В Python 3 этот модуль также содержит реализацию алгоритма «geohash», отсылку к комиксу xkcd 426. [37]

Ссылки

  1. ^ «Читаемость имеет значение». - PEP 20 - Дзен Python Архивировано 2014-12-05 на Wayback Machine
  2. ^ "PEP 20 - The Zen of Python". Python Software Foundation. 2004-08-23. Архивировано из оригинала 2008-12-03 . Получено 2008-11-24 .
  3. ^ "2. Лексический анализ". Документация Python 3. Python Software Foundation . Получено 2021-03-11 .
  4. ^ "2. Лексический анализ". Документация Python v2.7.18 . Python Software Foundation . Получено 2021-03-11 .
  5. ^ "Новые ключевые слова". Документация Python v3.5 . Docs.python.org. Архивировано из оригинала 2016-06-18 . Получено 2016-06-01 .
  6. ^ "2. Лексический анализ". Документация Python 3. Python Software Foundation . Получено 2022-01-22 .
  7. ^ "PEP 622 -- Структурное сопоставление шаблонов". 2020-06-23 . Получено 2022-01-22 .
  8. ^ "PEP 8 — Руководство по стилю кода Python". Python.org . Получено 17.03.2021 .
  9. ^ Хоффа, Фелипе (2017-07-26). «400 000 репозиториев GitHub, 1 миллиард файлов, 14 терабайт кода: пробелы или табуляции?». Medium . Получено 2021-03-11 .
  10. ^ "Табуляции или пробелы". ukupat.github.io . Получено 2021-03-11 .
  11. ^ "PEP 8 — Руководство по стилю кода Python". Python.org . Получено 11.03.2021 .
  12. ^ "PEP 498 - Literal String Interpolation". Что нового в Python 3.6 . 2016-12-23. Архивировано из оригинала 2017-03-30 . Получено 2017-03-29 .
  13. ^ "2. Лексический анализ". Документация Python v2.7.5 . Docs.python.org. Архивировано из оригинала 2012-10-23 . Получено 2013-08-16 .
  14. ^ "2. Лексический анализ". Документация Python v2.7.5 . Docs.python.org. Архивировано из оригинала 2012-10-23 . Получено 2013-08-16 .
  15. ^ Хешируемые элементы обычно неизменяемы, но не обязательно таковы по определению. См. python.org/3/glossary.htm
  16. ^ "6. Выражения — Документация Python 3.9.2". docs.python.org . Получено 2021-03-17 .
  17. ^ "Python 2.7.0 Release". Архивировано из оригинала 2016-01-27 . Получено 2016-01-19 .
  18. ^ "5. Структуры данных — документация Python 2.7.18". Архивировано из оригинала 2016-01-26 . Получено 2016-01-19 .
  19. ^ "5. Структуры данных — документация Python 2.7.18". Архивировано из оригинала 2016-01-26 . Получено 2016-01-19 .
  20. ^ Дэвид Мерц. "Функциональное программирование на Python". IBM developerWorks. Архивировано из оригинала 2007-02-20 . Получено 27-08-2007 .
  21. ^ "PEP 308 -- Условные выражения". Архивировано из оригинала 2016-03-13 . Получено 2016-04-14 .
  22. ^ Ключевое nonlocalслово было принято PEP 3104 Архивировано 2014-12-02 на Wayback Machine
  23. ^ "Python Style Guide". docs.python-guide.org. Архивировано из оригинала 2015-03-09 . Получено 2015-03-08 .
  24. ^ "PEP 343 -- Заявление "с"". Архивировано из оригинала 2014-12-14 . Получено 2014-08-15 .
  25. ^ "Глоссарий — Документация Python 3.9.2". docs.python.org . Получено 2021-03-23 ​​.
  26. ^ EAFP Архивировано 26 октября 2012 г. на Wayback Machine , Python Glossary
  27. ^ Хэмблен, Дайан. «Только пределы нашего воображения: эксклюзивное интервью с RADM Грейс М. Хоппер». Журнал информационных технологий Министерства ВМС. Архивировано из оригинала 14 января 2009 г. Получено 31 января 2007 г.
  28. ^ ab Python в двух словах, Алекс Мартелли , стр. 134
  29. ^ LBYL Архивировано 21.01.2018 в Wayback Machine , Python Glossary
  30. ^ Алекс Мартелли (19 мая 2003 г.). «EAFP против LBYL». Почтовая рассылка python-list. Архивировано из оригинала 14 июля 2012 г. Получено 18 июля 2011 г.
  31. ^ "PEP 8 — Руководство по стилю кода Python". Python.org . Получено 2021-03-23 .
  32. ^ ab "PEP 3107 -- Аннотации функций". Архивировано из оригинала 2015-01-06 . Получено 2014-08-15 .
  33. ^ "Python 2.4 Decorators: Reducing code duplication and consolidating knowledge" (Декораторы Python 2.4: Сокращение дублирования кода и консолидация знаний). Dr. Dobb's . 2005-05-01. Архивировано из оригинала 2007-02-06 . Получено 2007-02-08 .
  34. ^ "Новый декоратор рекурсии хвоста". ASPN: Python Cookbook . 2006-11-14. Архивировано из оригинала 2007-02-09 . Получено 2007-02-08 .
  35. ^ "Модуль декоратора". Архивировано из оригинала 2007-02-10 . Получено 2007-02-08 .
  36. ^ cpython: Язык программирования Python, Python, 2017-10-15, заархивировано из оригинала 2017-09-15 , извлечено 2017-10-15
  37. ^ "Еще одно скрытое сокровище. · python/cpython@b1614a7". GitHub . Получено 2017-10-15 .

Внешние ссылки