Главная страница
Навигация по странице:

  • Явные и неявные преобразования типов

  • Сценарии и программы, языки сценариев и языки программирования

  • Библиотеки, фреймворки, SDK, ядра и API

  • Не добавляйте и не удаляйте элементы из списка в процессе перебора

  • Чистыйкод дляпродолжающи х


    Скачать 7.85 Mb.
    НазваниеЧистыйкод дляпродолжающи х
    Дата13.05.2023
    Размер7.85 Mb.
    Формат файлаpdf
    Имя файлаPython_Chisty_kod_dlya_prodolzhayuschikh_2022_El_Sveygart.pdf
    ТипДокументы
    #1127485
    страница16 из 40
    1   ...   12   13   14   15   16   17   18   19   ...   40
    slices = 8
    >>> eaters = 0
    >>> print('Each person eats', slices / eaters, 'slices.')
    Этот код при запуске выдает трассировку:
    Traceback (most recent call last):
    File "
    ", line 1, in
    print('Each person eats', slices / eaters, 'slices.')
    ZeroDivisionError: division by zero
    Полезно помнить, что номер строки в трассировке относится только к точке, в ко- торой интерпретатор Python обнаружил ошибку. Истинная причина ошибки может находиться в предыдущей строке кода или даже намного ранее в программе.
    Синтаксические ошибки в исходном коде перехватываются интерпретатором до запуска программы, но синтаксические ошибки также происходят во время вы- полнения. Функция eval()
    может получить строку кода Python и выполнить его, что приводит к ошибке
    SyntaxError во время выполнения. Например, в команде eval('print("Hello,
    world)')
    пропущена закрывающая двойная кавычка, но про- грамма не обнаружит этот факт, пока не будет вызвана функция eval()
    Семантические (semantic) ошибки, также называемые логическими (logical), коварнее предыдущих. Семантические ошибки не порождают сообщений об ошибках или сбоев, но компьютер выполняет инструкции способом, который не предполагался программистом. На естественном языке семантическую ошибку можно сравнить с распоряжением: «Купи в магазине пакет молока, а если есть яйца — купи десяток».
    Тогда компьютер купит 11 пакетов молока, потому что в магазине есть яйца. Хоро- шо это или плохо, но компьютеры делают в точности то, что вы им приказываете.
    Например, введите следующий фрагмент в интерактивной оболочке:
    >>> print('The sum of 4 and 2 is', '4' + '2')
    Вы получите следующий результат:
    The sum of 4 and 2 is 42
    Очевидно,
    42
    не является правильным ответом. Но стоит заметить, что программа была выполнена без сбоев. Так как оператор Python
    +
    складывает целые числа и вы- полняет конкатенацию строковых значений, ошибочное использование строковых значений '4'
    и '2'
    вместо целых чисел привело к такой работе программы.

    Частые ошибки при использовании терминов
    159
    Параметры и аргументы
    Параметры (parameters) — имена переменных, заключенные в круглые скобки в команде def
    . Аргументами (arguments) называются значения, передаваемые при вызове функции, которые затем присваиваются параметрам. Например, введите следующий фрагмент в интерактивной оболочке:
    >>> def greeting(name, species):

    ... print(name + ' is a ' + description)
    >>> greeting('Zophie', 'cat')

    Zophie is a cat
    В команде def имена name и species
    — параметры

    . В вызове функции 'Zophie'
    и 'cat'
    — аргументы

    . Эти два термина часто путают. Помните, что параметры и аргументы — всего лишь другие названия для переменных и значений, когда они используются в этом контексте.
    Явные и неявные преобразования типов
    Объект одного типа можно преобразовать в объект другого типа. Например, int('42')
    преобразует строку '42'
    в целое число
    42
    . На самом деле строковый объект '42'
    не преобразуется, так как функция int()
    создает новый объект целого числа на основании исходного объекта. Явные преобразования правильнее на- зывать приведением типа (casting), хотя программисты все равно часто называют этот процесс преобразованием (converting) объекта.
    Python часто выполняет неявные преобразования типов (coercion) — например, когда вычисление выражения
    2
    +
    3.0
    дает результат
    5.0
    . Значения (такие как
    2
    и
    3.0
    ) преобразуются к общему типу данных, с которым может работать оператор.
    Неявные преобразования часто приводят к непредвиденным результатам. Логиче- ские значения
    True и
    False в Python могут быть преобразованы в целые числа
    1
    и
    0
    соответственно. Хотя в реальном коде логические значения никогда не записыва- ются в таком виде, это означает, что выражение
    True
    +
    False
    +
    True эквивалентно
    1
    +
    0
    +
    1
    и дает результат
    2
    . Зная этот факт, можно подумать, что передача списка ло- гических значений функции sum()
    позволит эффективно подсчитать значения
    True в списке. Но как выясняется, вызов метода count()
    для списка работает быстрее.
    Свойства и атрибуты
    Во многих языках термины «свойство» (property) и «атрибут» (attribute) ис- пользуются как синонимы, но в Python эти слова имеют разный смысл. Атрибут, как объяснялось в подразделе «Переменные и атрибуты» на с. 154, представляет

    160
    Глава 7.Жаргон программистов собой имя, связанное с объектом. К числу атрибутов относятся компонентные переменные и методы объекта.
    В других языках, таких как Java, классы могут содержать get- и set-методы. Вместо того чтобы напрямую присваивать атрибуту (возможно, недействительное) значе- ние, программа должна вызвать set-метод для этого атрибута.
    Код в set-методе может гарантировать, что компонентной переменной будут при- сваиваться только действительные значения. Get-метод читает значение атрибута.
    Если атрибуту, допустим, присвоено имя accountBalance
    , set- и get-методам обычно присваиваются имена setAccountBalance()
    и getAccountBalance()
    соответственно.
    В Python свойства позволяют программистам использовать get- и set-методы с более чистым синтаксисом. В главе 17 я более подробно расскажу о свойствах Python.
    Байт-код и машинный код
    Исходный код компилируется в так называемый машинный код (machine code) — инструкции, которые могут непосредственно выполняться процессором. Ма- шинный код состоит из инструкций из встроенного набора команд (instruction set) процессора. Откомпилированная программа, состоящая из машинного кода, называется двоичным файлом (binary). Для таких уважаемых языков, как C, су- ществуют специальные программы — компиляторы; они преобразуют исходный файл с кодом C в двоичные файлы почти для любых существующих процессоров.
    Но если вы хотите, чтобы Python работал на таком же наборе процессоров, на на- писание компилятора Python для каждого процессора потребуется масса времени.
    Также существует другой механизм преобразования исходного кода в код, который может выполняться машиной. Вместо машинного кода, который выполняется не- посредственно процессором, можно создать байт-код (bytecode). Байт-код, также называемый портируемым (portable) кодом, или p-кодом, выполняется не напрямую процессором, а специальной программой — интерпретатором. Байт-код Python состоит из инструкций, хотя эти инструкции не выполняются ни одним реально существующим процессором. Вместо этого интерпретатор выполняет байт-код.
    Байт-код Python сохраняется в файлах
    .pyc
    , которые иногда встречаются среди исходных файлов
    .py
    . Интерпретатор CPython, написанный на C, может компили- ровать исходный код Python в байт-код Python, а затем выполнять эти инструкции.
    (Это относится и к виртуальной машине Java [JVM], выполняющей байт-код языка
    Java.) Так как интерпретатор CPython написан на C, он может быть откомпилирован для любого процессора, для которого уже существует компилятор C.
    Если вам захочется больше узнать обо всем этом, есть отличный источник — до- клад Скотта Сэндерсона (Scott Sanderson) и Джо Джевника (Joe Jevnik) «Playing with Python Bytecode» на конференции PyCon 2016 (https://youtu.be/mxjv9KqzwjI).

    Частые ошибки при использовании терминов
    161
    Сценарии и программы, языки сценариев и языки программирования
    Различия между сценарием (script) и программой, и даже языком сценариев и языком программирования, весьма туманны и субъективны. Можно с полным основанием утверждать, что все сценарии являются программами, а все языки сце- нариев являются языками программирования. Тем не менее языки сценариев иногда считаются более простыми, или «неполноценными», языками программирования.
    Один из признаков, отличающих сценарии от программ, — способ выполнения кода.
    Сценарии, написанные на языках сценариев, интерпретируются непосредственно из исходного кода, тогда как программы, написанные на языках программирова- ния, компилируются в двоичные файлы. Однако Python обычно рассматривается как язык сценариев, хотя при запуске программы Python существует этап компи- ляции в байт-код. При этом Java обычно языком сценариев не считается, хотя он и генерирует байт-код вместо двоичных файлов с машинным кодом, как и Python.
    С технической точки зрения языки не компилируются и не интерпретируются; правильнее сказать, что существуют компилируемые и интерпретируемые реали- зации языка, и компилятор или интерпретатор можно создать для любого языка.
    Эти различия вызывают споры, но в конечном итоге они не настолько важны. Языки сценариев вовсе не обязательно обладают меньшей мощью, а с компилируемыми языками не всегда труднее работать.
    Библиотеки, фреймворки, SDK, ядра и API
    Использование кода, написанного другими людьми, сильно экономит время. Такой код часто доступен в виде библиотек, фреймворков, SDK, ядер или API. И здесь надо понимать различия между ними.
    Библиотека (library) — общий термин для подборки кодов, написанных третьей стороной. Библиотека может содержать функции, классы или другие фрагменты кода, предназначенные для использования разработчиками. Библиотека Python может быть реализована в виде пакета, набора пакетов и даже отдельного модуля.
    Библиотеки часто предназначены для конкретного языка. Разработчикам не обяза- тельно знать, как работает код библиотеки; им достаточно знать, как вызывать код из библиотеки или взаимодействовать с ним. Стандартная библиотека (например, стандартная библиотека Python) представляет собой программную библиотеку, которая должна быть доступна для всех реализаций языка программирования.
    Фреймворком (framework) называется подборка кода, работающая по принципу инверсии управления; разработчик пишет функции, которые вызываются фрейм- ворком по мере надобности (вместо вызова функций фреймворка из кода разработ- чика). Инверсия управления часто описывается фразой «не звоните нам, мы сами вам позвоним». Например, при написании кода для фреймворка веб-приложений

    162
    Глава 7.Жаргон программистов разработчику приходится создавать для веб-страниц функции, которые будут вы- зываться фреймворком при поступлении веб-запроса.
    SDK (Software Development Kit — комплект разработки ПО) — это программные библиотеки, документация и программные средства, упрощающие создание при- ложений для конкретной операционной системы или платформы. Например,
    Android SDK и iOS SDK используются для создания мобильных приложений для
    Android и iOS соответственно. JDK (Java Development Kit) — SDK для создания приложений для JVM.
    Ядро, или движок (engine), — крупная автономная система, которой могут управ- лять внешние программы разработчика. Разработчики обычно вызывают функции ядра для выполнения больших сложных задач. Примеры — игровые и физические движки, рекомендательные системы, ядра баз данных, ядра для шахматной игры и поисковые системы.
    Интерфейс прикладного программирования, или API (Application Programming
    Interface), — интерфейс для работы с библиотекой, SDK, фреймворком или ядром, предназначенный для внешнего использования. API указывает, как вызывать функции или обращаться с запросами к библиотеке для получения доступа к ее ресурсам. Создатели библиотеки (обычно) публикуют документацию API. Многие популярные социальные сети и веб-сайты предоставляют HTTP API, для того чтобы их услугами могли пользоваться программы (а не только люди с веб-браузерами).
    Используя такие API, можно писать программы, которые, например, автоматически публикуют сообщения в Facebook или читают потоки сообщений Twitter.
    Итоги
    Даже программист с многолетним опытом не всегда знает все термины из области программирования. Но крупные программные продукты обычно создаются коман- дами разработчиков, а не отдельными людьми. Таким образом, однозначность терминологии играет важную роль при работе в команде.
    Теперь вы знаете, что программы Python строятся из идентификаторов, переменных, литералов, ключевых слов и объектов, а каждый объект Python характеризуется значением, типом данных и идентичностью. И хотя каждый объект обладает типом данных, также существуют более широкие категории типов: контейнеры, после- довательности, отображения, множества, встроенные типы и типы, определяемые пользователем.
    Некоторые понятия (скажем, значения, переменные и функции) могут по-разному называться в особых контекстах — например, элементы, параметры, аргументы и методы. Также программисты нередко путают некоторые термины друг с другом.

    Дополнительные ресурсы
    163
    В повседневном программировании путаница в таких терминах, как свойства/
    атрибуты, блок/тело, исключение/ошибка, тонкостях различий между библиоте- ками, фреймворками, SDK, ядрами и API не создаст особых проблем. Иногда при неправильном выборе термина ваш код будет нормально работать, но вы будете выглядеть непрофессионально; например, новички часто считают синонимами такие понятия, как команда и выражение, функция и метод, параметр и аргумент.
    А вот такие термины, как итерируемый объект и итератор, синтаксическая ошибка и семантическая ошибка, байт-код и машинный код, имеют разный смысл. Никогда не путайте их, если только вы не хотите запутать своих коллег.
    При этом смысл терминов может изменяться в зависимости от языка и даже от программиста. Со временем и по мере накопления опыта (и количества обраще- ний в интернете) вы начнете более уверенно чувствовать себя при использовании жаргона.
    Дополнительные ресурсы
    В официальном глоссарии Python (https://docs.python.org/3/glossary.html) приведе- ны короткие, но полезные определения, используемые в экосистеме Python. В офи- циальной документации Python (https://docs.python.org/3/reference/datamodel.html) объекты Python описываются более подробно.
    В докладе Нины Захаренко (Nina Zakharenko) «Memory Management in Python —
    The Basics» на конференции PyCon 2016 (https://youtu.be/F6u5rhUQ6dU) объ- ясняются многие аспекты работы сборщика мусора в Python. Официальная до- кументация Python (https://docs.python.org/3/library/gc.html) содержит больше информации о работе сборщика мусора.
    Также полезно ознакомиться с обсуждением перехода на упорядоченные словари в Python 3.6 в списке рассылки Python (https://mail.python.org/pipermail/python-
    dev/2016-September/146327.html).

    8
    Часто встречающиеся
    ловушки Python
    Хотя Python и является моим любимым языком програм- мирования, он не лишен недостатков. У каждого языка есть свои раздражающие особенности (в некоторых языках их больше, чем в других), и Python не исключение. Неопытные программисты, работающие на Python, должны знать некоторые часто встречающиеся ловушки и уметь избегать их.
    Как правило, такие знания люди получают на собственном опыте, а я собрал ин- формацию о них в этой главе. Если вы будете знать историю таких ловушек, вам будет легче понять, почему Python иногда ведет себя немного странно.
    В этой главе я расскажу, как изменяемые объекты, такие как списки и словари, на- чинают вести себя неожиданно при изменении их содержимого. Вы узнаете, почему метод sort()
    не сортирует элементы строго по алфавиту, а числа с плавающей точ- кой могут содержать ошибки округления, почему операторы проверки неравенства
    !=
    has демонстрируют непредсказуемое поведение при сцеплении, а при записи кортежей, содержащих только один элемент, необходимо включать завершающую запятую. Ну и конечно, из этой главы вы узнаете, как обойти все эти ошибки.
    Не добавляйте и не удаляйте элементы из списка
    в процессе перебора
    Добавление или удаление элементов из списка в процессе его перебора в цикле for или while с большой вероятностью приведет к ошибке. Рассмотрим следующий сценарий: вы хотите перебрать список строк с описаниями предметов одежды

    Не добавляйте и не удаляйте элементы из списка в процессе перебора
    165
    и позаботиться о том, чтобы список содержал четное количество носков; для этого каждый раз, когда в списке обнаруживается один носок, в список добавляется пара для него. Задача кажется тривиальной; нужно перебрать строки из списка и при обнаружении в строке текста 'sock'
    (например,
    'red sock'
    ) в список будет добав- ляться еще один элемент 'red sock'
    Но этот код работать не будет. Программа входит в бесконечный цикл, который приходится прерывать нажатием клавиш
    Ctrl-C
    :
    >>> clothes = ['skirt', 'red sock']
    >>> for clothing in clothes: # Перебрать список.
    ... if 'sock' in clothing: # Найти строки, содержащие 'sock'.
    ... clothes.append(clothing) # Добавить парный элемент.
    ... print('Added a sock:', clothing) # Сообщить пользователю.
    Added a sock: red sock
    Added a sock: red sock
    Added a sock: red sock
    Added a sock: red sock
    Traceback (most recent call last):
    File "", line 3, in
    KeyboardInterrupt
    Процесс выполнения этого кода наглядно представлен по адресу https://autbor.
    com/addingloop/.
    Проблема в том, что при добавлении в список clothes элемента 'red sock'
    в списке появляется новый, третий элемент, который тоже должен быть включен в перебор:
    ['skirt',
    'red sock',
    'red sock']
    . Цикл for достигает второго элемента 'red sock'
    при следующей итерации, и он присоединяет вторую строку 'red sock'
    . Список пре- образуется к виду
    ['skirt',
    'red sock',
    'red sock',
    'red sock']
    , и в нем появляется еще одна строка, которая должна быть включена в перебор. Все это продолжается, как показано на рис. 8.1, и в результате вы получаете бесконечный поток сообще- ний 'Added a
    sock.
    '. Цикл останавливается только тогда, когда на компьютере будет исчерпана вся свободная память и программа Python аварийно завершится или вы прервете программу клавишами
    Ctrl-C
    Вывод: не добавляйте элементы в список во время перебора. Вместо этого создайте отдельный список для содержимого измененного списка, такой как newClothes в этом примере:
    >>>
    1   ...   12   13   14   15   16   17   18   19   ...   40


    написать администратору сайта