Глава 1. Ваша первая программа на Python

Добавлено 2 апреля 2020 в 21:12

Не убегайте от проблем, не осуждайте себя и не несите своё бремя в праведном безмолвии. У вас есть проблема? Прекрасно! Это пойдёт на пользу! Радуйтесь: погрузитесь в неё и исследуйте!

Содержание главы

Погружение

Обычно книги о программировании начинаются с кучи скучных глав о базовых вещах и постепенно переходят к созданию чего-нибудь полезного. Давайте всё это пропустим. Вот вам готовая, работающая программа на Python. Возможно, вы ровным счётом ничего в ней не поймёте. Не беспокойтесь об этом, скоро мы разберём её строчка за строчкой. Но сначала прочитайте код и посмотрите, что вы сможете извлечь из него.

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}

def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    '''Преобразует размер файла в удобочитаемую для человека форму.

    Ключевые аргументы:
    size -- размер файла в байтах
    a_kilobyte_is_1024_bytes -- если True (по умолчанию), используются степени 1024
                                если False, используются степени 1000

    Возвращает: текстовую строку (string)

    '''
    if size < 0:
        raise ValueError('число должно быть неотрицательным')

    multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
    for suffix in SUFFIXES[multiple]:
        size /= multiple
        if size < multiple:
            return '{0:.1f} {1}'.format(size, suffix)

    raise ValueError('число слишком большое')

if __name__ == '__main__':
    print(approximate_size(1000000000000, False))
    print(approximate_size(1000000000000))

Теперь давайте запустим эту программу из командной строки. В Windows это будет выглядеть примерно так:

c:\home\diveintopython3\examples> c:\python31\python.exe humansize.py
1.0 TB
931.3 GiB

В Mac OS X и Linux, будет почти то же самое:

you@localhost:~/diveintopython3/examples$ python3 humansize.py
1.0 TB
931.3 GiB

Что сейчас произошло? Вы выполнили свою первую программу на Python. Вы вызвали интерпретатор Python в командной строке и передали ему имя скрипта, который хотели выполнить. В скрипте определена функция approximate_size(), которая принимает точный размер файла в байтах и вычисляет «красивый» (но приблизительный) размер. (Возможно, вы видели его в Проводнике Windows, в Mac OS X Finder, в Nautilus, Dolphin или Thunar в Linux. Если отобразить папку с документами в виде таблицы, файловый менеджер в каждой её строке покажет иконку, название документа, размер, тип, дату последнего изменения и т. д. Если в папке есть 1093-байтовый файл с названием «TODO», файловый менеджер не покажет «TODO 1093 байта»; вместо этого он скажет что-то типа «TODO 1 КБ». Именно это и делает функция approximate_size().)

Посмотрите на последние строки скрипта, вы увидите два вызова print(approximate_size(аргументы)). Это вызовы функций. Сначала вызывается approximate_size(), которой передаётся несколько аргументов, а затем возвращённое ею значение берётся и передаётся прямо в функцию print(). Функция print() встроенная, вы нигде не найдёте её явного объявления. Её можно только использовать, где угодно и когда угодно. (Есть множество встроенных функций, и ещё больше функций, которые выделены в отдельные модули. Только терпение, непоседа.)

Итак, почему при выполнении скрипта в командной строке, всегда получается один и тот же результат? Мы ещё дойдём до этого. Но сначала давайте посмотрим на функцию approximate_size().

1.2 Объявление функций

Когда вам нужна функция, просто объявите её.

В Python есть функции, как и в большинстве других языков, но нет ни отдельных заголовочных файлов, как в C++, ни конструкций interface/implementation, как в Паскале. Когда вам нужна функция, просто объявите её, например, так:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

Объявление начинается с ключевого слова def, затем следует имя функции, а за ним аргументы в скобках. Если аргументов несколько, они разделяются запятыми.

К тому же, стоит заметить, что в объявлении функции не задаётся тип возвращаемых данных. Функции в Python не определяют тип возвращаемых ими значений; они даже не указывают, существует ли возвращаемое значение вообще. (На самом деле, любая функция в Python возвращает значение; если в функции выполняется инструкция return, она возвращает указанное в этой инструкции значение, если нет – возвращает None – специальное нулевое значение.)

В некоторых языках программирования функции (возвращающие значение) объявляются ключевым словом function, а подпрограммы (не возвращающие значений) – ключевым словом sub. В Python же подпрограмм нет. Все функции возвращают значение (даже если оно None), и всегда объявляются ключевым словом def.

Функция approximate_size() принимает два аргумента: size и a_kilobyte_is_1024_bytes, но ни один из них не имеет типа. В Python тип переменных никогда не задаётся явно. Python вычисляет тип переменной и следит за ним самостоятельно.

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

1.2.1 Необязательные и именнованные аргументы

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

Давайте ещё раз посмотрим на объявление функции approximate_size():

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

Второй аргумент – a_kilobyte_is_1024_bytes – записывается со значением по умолчанию True. Это означает, что этот аргумент необязательный; можно вызвать функцию без него, а Python будет действовать так, как будто она вызвана с True в качестве второго параметра.

Теперь взглянем на последние строки скрипта:

if __name__ == '__main__':
    print(approximate_size(1000000000000, False))  ①
    print(approximate_size(1000000000000))         ②
  1. Строка 27. Функция approximate_size() вызывается с двумя аргументами. Внутри функции approximate_size() переменная a_kilobyte_is_1024_bytes будет False, поскольку False передаётся явно во втором аргументе.
  2. Строка 28. Функция approximate_size() вызывается только с одним аргументом. Но всё в порядке, потому что второй аргумент необязателен! Поскольку второй аргумент не указан, он принимает значение по умолчанию True, как определено в объявлении функции.

А ещё можно передавать значения в функцию по имени.

>>> from humansize import approximate_size
>>> approximate_size(4000, a_kilobyte_is_1024_bytes=False)       ①
'4.0 KB'
>>> approximate_size(size=4000, a_kilobyte_is_1024_bytes=False)  ②
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, size=4000)  ③
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, 4000)       ④
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> approximate_size(size=4000, False)                           ⑤
  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

Перевод сообщений оболочки

  File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

Файл "<stdin>", строка 1
SyntaxError: неименованный аргумент после именованного

  1. Строка 2. Функция approximate_size() вызывается со значением 4000 в первом аргументе и False в аргументе по имени a_kilobyte_is_1024_bytes. (Он стоит на втором месте, но это не важно, как вы скоро увидите.)
  2. Строка 4. Функция approximate_size() вызывается со значением 4000 в аргументе по имени size и False в аргументе по имени a_kilobyte_is_1024_bytes. (Эти именованные аргументы стоят в том же порядке, в каком они перечислены в объявлении функции, но это тоже не важно.)
  3. Строка 6. Функция approximate_size() вызывается с False в аргументе по имени a_kilobyte_is_1024_bytes и 4000 в аргументе по имени size. (Видите? Я же говорил, что порядок не важен.)
  4. Строка 8. Этот вызов не работает, потому что за именованным аргументом следует неименованный (позиционный). Если читать список аргументов слева направо, то как только встречается именованный аргумент, все следующие за ним аргументы тоже должны быть именованными.
  5. Строка 11. Этот вызов тоже не работает, по той же причине, что и предыдущий. Удивительно? Ведь сначала передаётся 4000 в аргументе по имени size, затем, «очевидно», можно ожидать, что False станет аргументом по имени a_kilobyte_is_1024_bytes. Но в Python это не работает. Раз есть именованный аргумент, все аргументы справа от него тоже должны быть именованными.

1.3 Написание читаемого кода

Не буду растопыривать перед вами пальцы и мучить длинной лекцией о важности документирования кода. Просто знайте, что код пишется один раз, а читается многократно, и самый важный читатель вашего кода – это вы сами через полгода после написания (т. е. всё уже забыто, и вдруг понадобилось что-то починить). В Python писать читаемый код просто. Используйте это его преимущество и через полгода вы скажете мне «спасибо».

1.3.1 Строки документации

Каждая функция заслуживает хорошую документацию.

Функции в Python можно документировать, снабжая их строками документации (англ. documentation string, сокращённо docstring). В нашей программе у функции approximate_size() есть строка документации:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):
    '''Преобразует размер файла в удобочитаемую для человека форму.

    Ключевые аргументы:
    size -- размер файла в байтах
    a_kilobyte_is_1024_bytes -- если True (по умолчанию), используются степени 1024
                                если False, используются степени 1000

    Возвращает: текстовую строку (string)

    '''

Тройные кавычки (три апострофа) используются для задания строк (имеется ввиду тип данных string) содержащих многострочный текст. Всё, что находится между начальными и конечными кавычками, является частью одной строки данных, включая переводы строк, пробелы в начале каждой строки текста, и другие кавычки. Вы можете использовать их где угодно, но чаще всего будете встречать их в определениях строк документации.

Тройные кавычки – это ещё и простой способ определить строку, содержащую одинарные (апострофы) и двойные кавычки, подобно qq/.../ в Perl 5.

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

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

1.4 Путь поиска оператора import

Перед тем, как идти дальше, я хочу вкратце рассказать о путях поиска библиотек. Когда вы пытаетесь импортировать модуль (с помощью оператора import), Python ищет его в нескольких местах. В частности, он ищет во всех директориях, перечисленных в sys.path. Это просто список, который можно легко просматривать и изменять при помощи стандартных списочных методов. (Вы узнаете больше о списках в главе «Встроенные типы данных».)

>>> import sys                                                 ①
>>> sys.path                                                   ②
['', 
 '/usr/lib/python31.zip', 
 '/usr/lib/python3.1',
 '/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@', 
 '/usr/lib/python3.1/lib-dynload', 
 '/usr/lib/python3.1/dist-packages', 
 '/usr/local/lib/python3.1/dist-packages']
>>> sys                                                        ③
<module 'sys' (built-in)>
>>> sys.path.insert(0, '/home/mark/diveintopython3/examples')  ④
>>> sys.path                                                   ⑤
['/home/mark/diveintopython3/examples', 
 '', 
 '/usr/lib/python31.zip', 
 '/usr/lib/python3.1', 
 '/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@', 
 '/usr/lib/python3.1/lib-dynload', 
 '/usr/lib/python3.1/dist-packages', 
 '/usr/local/lib/python3.1/dist-packages']
  1. Строка 1. Импортирование модуля sys делает доступными все его функции и атрибуты.
  2. Строка 2.sys.path – список имён директорий, определяющий текущий путь поиска. (Ваш будет выглядеть иначе, в зависимости от вашей операционной системы, от используемой версии Python и от того, куда он был установлен.) Python будет искать в этих директориях (в заданном порядке) файл с расширением «.py», имя которого совпадает с тем, что вы пытаетесь импортировать.
  3. Строка 10. Вообще-то я вас обманул; истинное положение дел немного сложнее, потому что не все модули лежат в файлах с расширением «.py». Некоторые из них, как, например, модуль sys, являются встроенными; они впаяны в сам Python. Встроенные модули ведут себя точно так же, как обычные, но их исходный код недоступен, потому что они не были написаны на Python! (Модуль sys написан на Си.)
  4. Строка 12. Можно добавить новую директорию в путь поиска, добавив имя директории в список sys.path, во время выполнения Python, и тогда Python будет просматривать её наравне с остальными, как только вы попытаетесь импортировать модуль. Новый путь поиска будет действителен в течение всего сеанса работы Python.
  5. Строка 13. Выполнив команду sys.path.insert(0, новый_путь), вы вставили новую директорию на первое место в список sys.path, и, следовательно, в начало пути поиска модулей. Почти всегда, именно это вам и нужно. В случае конфликта имён (например, если Python поставляется со 2-й версией некоторой библиотеки, а вы хотите использовать версию 3) этот приём гарантирует, что будут найдены и использованы ваши модули, а не те, которые идут в комплекте с Python.

1.5 Всё является объектом

Если вы вдруг пропустили, я только что сказал, что функции в Python имеют атрибуты, и эти атрибуты доступны во время выполнения. Функция, как и всё остальное в Python, является объектом.

Запустите интерактивную оболочку Python и повторите за мной:

>>> import humansize                               ①
>>> print(humansize.approximate_size(4096, True))  ②
4.0 KiB
>>> print(humansize.approximate_size.__doc__)      ③
Преобразует размер файла в удобочитаемую для человека форму.

    Ключевые аргументы:
    size -- размер файла в байтах
    a_kilobyte_is_1024_bytes -- если True (по умолчанию), используются степени 1024
                                если False, используются степени 1000

    Возвращает: текстовую строку (string)
  1. Строка 1. Первая строка импортирует программу humansize в качестве модуля – фрагмента кода, который можно использовать интерактивно или из другой Python-программы. После того, как модуль был импортирован, можно обращаться ко всем его публичным функциям, классам и атрибутам. Импорт применяется как в модулях, для доступа к функциональности других модулей, так и в интерактивной оболочке Python. Это очень важная идея, и вы ещё не раз встретите её на страницах этой книги.
  2. Строка 2. Когда вы хотите использовать функцию, определённую в импортированном модуле, нужно дописать к её имени название модуля. То есть вы не можете использовать просто approximate_size, обязательно humansize.approximate_size. Если вы использовали классы в Java, то для вас это должно быть знакомо.
  3. Строка 4. Вместо того, чтобы вызвать функцию (как вы, возможно, ожидали), вы запросили один из её атрибутов – __doc__.

Оператор import в Python похож на require из Perl. После import в Python, вы обращаетесь к функциям модуля как модуль.функция; после require в Perl, для обращения к функциям модуля используется имя модуль::функция.

1.5.1 Что такое объект?

В языке Python всё является объектом, и у любого объекта могут быть атрибуты и методы. Все функции имеют стандартный атрибут __doc__, содержащий строку документации, определённую в исходном коде функции. Модуль sys – тоже объект, имеющий (кроме прочего) атрибут под названием path. И так далее.

Но мы так и не получили ответ на главный вопрос: что такое объект? Разные языки программирования определяют «объект» по-разному. В одних считается, что все объекты должны иметь атрибуты и методы. В других, что объекты могут порождать подклассы. В Python определение ещё менее чёткое. Некоторые объекты не имеют ни атрибутов, ни методов, хотя и могли бы их иметь. Не все объекты порождают подклассы. Но всё является объектом в том смысле, что может быть присвоено переменной или передано функции в качестве аргумента.

Возможно, вы встречали термин «объект первого класса» в других книгах о программировании. В Python функции – объекты первого класса. Функцию можно передать в качестве аргумента другой функции. Модули – объекты первого класса. Весь модуль целиком можно передать в качестве аргумента функции. Классы – объекты первого класса, и отдельные их экземпляры – тоже объекты первого класса.

Это очень важно, поэтому я повторю это, на случай если вы пропустили первые несколько раз: всё в Python является объектом. Строки – это объекты. Списки – объекты. Функции – объекты. Классы – объекты. Экземпляры классов – объекты. И даже модули являются объектами.

1.6 Отступы

Функции в Python не имеют ни явных указаний begin и end, ни фигурных скобок, которые бы показывали, где код функции начинается, а где заканчивается. Разделители – только двоеточие (:) и отступы самого кода.

def approximate_size(size, a_kilobyte_is_1024_bytes=True):     ①
    if size < 0:                                               ②
        raise ValueError('число должно быть неотрицательным')  ③
                                                               ④
    multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
    for suffix in SUFFIXES[multiple]:                          ⑤
        size /= multiple
        if size < multiple:
            return '{0:.1f} {1}'.format(size, suffix)

    raise ValueError('число слишком большое')
  1. Строка 1. Блоки кода определяются по их отступам. Под «блоками кода» я подразумеваю функции, блоки if, циклы for и while и т. д. Увеличение отступа начинает блок, а уменьшение – заканчивает. Ни скобок, ни ключевых слов. Это означает, что важное значение имеют пробелы, и их количество тоже. В этом примере код функции имеет отступ в четыре пробела. Здесь не обязательно должно быть именно четыре пробела, просто их число должно быть постоянным. Первая встретившаяся строчка без отступа будет означать конец функции.
  2. Строка 2. За оператором if должен следовать блок кода. Если в результате вычисления условного выражения оно окажется истинным, то выполнится блок, выделенный отступом, в противном случае произойдёт переход к блоку else (если он есть). Обратите внимание, что нет скобок вокруг выражения.
  3. Строка 3. Эта строка находится внутри блока if. Оператор raise вызывает исключение (типа ValueError), но только если size < 0.
  4. Строка 4. Это ещё не конец функции. Совсем пустые строки не считаются. Они могут повысить читаемость кода, но не могут служить разделителями блоков кода. Блок кода функции продолжается на следующей строке.
  5. Строка 6. Оператор цикла for тоже начинает блок кода. Блоки кода могут содержать несколько строк, а именно – столько, сколько строк имеют такую же величину отступа. Этот цикл for содержит три строки кода. Других синтаксических конструкций для описания многострочных блоков кода нет. Просто делайте отступы, и будет вам счастье!

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

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

1.7 Исключения

Исключения (англ. exceptions – нештатные, исключительные ситуации, требующие специальной обработки) используются в Python повсюду. Буквально каждый модуль в стандартной библиотеке Python использует их, да и сам Python вызывает их во многих ситуациях. Вы ещё неоднократно встретите их на страницах этой книги.

Что такое исключение? Обычно это ошибка, признак того, что что-то пошло не так. (Не все исключения являются ошибками, но пока это не важно.) В некоторых языках программирования принято возвращать код ошибки, который вы потом проверяете. В Python принято использовать исключения, которые вы обрабатываете.

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

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

Результат исключения – это не всегда полный крах программы. Исключения можно обработать. Иногда исключения возникают из-за настоящих ошибок в вашем коде (например, доступ к переменной, которая не существует), но порой исключение – это нечто, что вы можете предвидеть. Если вы открываете файл, он может не существовать. Если вы импортируете модуль, он может быть не установлен. Если вы подключаетесь к базе данных, она может быть недоступна или у вас может быть недостаточно прав для доступа к ней. Если вы знаете, что какая-то строка кода может вызвать исключение, то его следует обработать с помощью блока try...except.

Python использует для обработки исключений блоки try...except, а для их генерации – оператор raise. Java и C++ используют для обработки исключений блоки try...catch, а для их генерации – оператор throw.

Функция approximate_size() вызывает исключение в двух разных случаях: если переданный ей размер (size) больше, чем функция может обработать, или если он меньше нуля.

if size < 0:
    raise ValueError('число должно быть неотрицательным')

Синтаксис вызова исключений достаточно прост. Надо написать оператор raise, за ним название исключения и опционально, поясняющую строку для отладки. Синтаксис напоминает вызов функции. (На самом деле, исключения реализованы как классы, и оператор raise просто создаёт экземпляр класса ValueError и передаёт в его метод инициализации строку 'число должно быть неотрицательным'. Но мы забегаем вперёд!)

Нет необходимости обрабатывать исключение в той функции, которая его вызвала. Если одна функция не обработает его, исключение передаётся в функцию, вызвавшую эту, затем в функцию, вызвавшую вызвавшую, и т. д. «вверх по стеку». Если исключение нигде не будет обработано, то программа упадёт, а Python выведет «раскрутку стека» (англ. traceback) в стандартный поток ошибок – и на этом конец. Повторяю, возможно, это именно то, что вам нужно, – это зависит от того, что делает ваша программа.

1.7.1 Отлов ошибок импорта

Одно из встроенных исключений Python – ImportError (ошибка импорта), которое вызывается, если не удаётся импортировать модуль. Это может случиться по нескольким причинам, самая простая из которых – отсутствие модуля в пути поиска, оператора import. Вы можете использовать это для включения в программу опциональных возможностей. Например, библиотека chardet предоставляет возможность автоматического определения кодировки символов. Предположим, ваша программа хочет использовать эту библиотеку в том случае, если она есть, или спокойно продолжить работу, если пользователь не установил её. Можно сделать это с помощью блока try...except.

try:
  import chardet
except ImportError:
  chardet = None

После этого можно проверять наличие модуля chardet простым if:

if chardet:
  # что-то сделать
else:
  # продолжить дальше

Другое частое применение исключения ImportError – выбор из двух модулей, предоставляющих одинаковый интерфейс (API), причём применение одного из них предпочтительнее другого (может, он быстрее работает или требует меньше памяти). Для этого можно попытаться импортировать сначала один модуль, и если это не удалось , то импортировать другой. К примеру, в главе XML рассказывается о двух модулях, реализующих один и тот же API, так называемый ElementTree API. Первый – lxml – сторонний модуль, который необходимо скачивать и устанавливать самостоятельно. Второй – xml.etree.ElementTree – медленнее, но входит в стандартную библиотеку Python 3.

try:
    from lxml import etree
except ImportError:
    import xml.etree.ElementTree as etree

При выполнении этого блока try...except будет импортирован один из двух модулей под именем etree. Поскольку оба модуля реализуют один и тот же API, то в последующем коде нет необходимости проверять, какой из этих модулей был импортирован. И раз импортированный модуль в любом случае именуется как etree, то не придётся вставлять лишние if для обращения к разноимённым модулям.

1.8 Несвязанные переменные

Взглянем ещё раз на вот эту строку функции approximate_size():

multiple = 1024 if a_kilobyte_is_1024_bytes else 1000

Мы нигде не объявляли переменную multiple (множитель), мы только присвоили ей значение. Всё в порядке, Python позволяет так делать. Что он не позволит сделать, так это обратиться к переменной, которой не было присвоено значение. Если попытаться так сделать, возникнет исключение NameError (ошибка в имени).

>>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> x = 1
>>> x
1

Перевод сообщения оболочки

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

Раскрутка стека (список последних вызовов):
Файл "<stdin>", строка 1, <модуль>
NameError: имя 'x' не определено

Однажды вы скажете Python «спасибо» за это.

1.9 Всё чувствительно к регистру

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

>>> an_integer = 1
>>> an_integer
1
>>> AN_INTEGER
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'AN_INTEGER' is not defined
>>> An_Integer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'An_Integer' is not defined
>>> an_inteGer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'an_inteGer' is not defined

Перевод сообщений оболочки

Раскрутка стека (список последних вызовов):
Файл "<stdin>", строка 1, <модуль>
NameError: имя '<имя>' не определено

1.10 Запуск скриптов

В Python всё является объектом.

Модули Python – это объекты, имеющие несколько полезных атрибутов. И это обстоятельство можно использовать для простого тестирования модулей, при их написании, путём включения специального блока кода, который будет выполняться при запуске файла из командной строки. Взгляните на последние строки humansize.py:

if __name__ == '__main__':
    print(approximate_size(1000000000000, False))
    print(approximate_size(1000000000000))

Как и в C, в Python оператор == используется для проверки на равенство, а оператор = используется для присваивания. Но в отличие от C, Python не поддерживает присваивание внутри другого выражения, поэтому у вас не получится случайно присвоить значение вместо проверки на равенство.

Итак, что же делает этот блок if особенным? У всех модулей, как у объектов, есть встроенный атрибут __name__ (имя). И значение этого атрибута зависит от того, как модуль используется. Если модуль импортируется, то __name__ принимает значение равное имени файла модуля, без расширения и пути к каталогу.

>>> import humansize
>>> humansize.__name__
'humansize'

Но модуль можно запустить и напрямую, как самостоятельную программу, в этом случае __name__ примет специальное значение по умолчанию, __main__. Python вычислит значение условного выражения в операторе if, определит его истинность, и выполнит блок кода if. В данном случае, будут напечатаны два значения.

c:\home\diveintopython3> c:\python31\python.exe humansize.py
1.0 TB
931.3 GiB

И это ваша первая программа на Python!

1.11 Материалы для дальнейшего чтения

Источник:

  • Mark Pilgrim. Dive Into Python 3

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.


  • 2021-01-10radioprog

    А python у вас куда установлен? У меня, например, в C:\Python\Python38
    Измените команду с учетом пути к python.exe

  • 2021-01-09Сергей Клементьев

    При вводе в командной строке c:\home\diveintopython3\examples> c:\python31\python.exe humansize.py
    Выдает: Системе не удается найти указанный путь.