Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Алгоритмизация и программирование. Язык Python. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
06.09.2026
Размер:
1 Мб
Скачать
5.6. Подробнее об условиях
Условия, используемые в операторах while и if могут содержать любые операторы, а не только сравнения.
Операторы сравнения in и not in проверяют, встречается ли (или нет) значение в последовательности. Операторы is и is not проверяют, являются ли
два объекта действительно одним и тем же объектом; это имеет значение только для изменяемых объектов, как списки. У всех операторов сравнения
одинаковый приоритет, который ниже, чем у всех численных операторов.
Сравнения могут быть объединены в цепь. Например, а < b = = c проверяет, меньше ли a, чем b, и вдобавок b равно ли c.
Сравнения могут быть объединены с помощью логических
операторов and и or, а результат сравнения (или любого другого логического выражения) может быть перевернут на обратный с помощью not. У этих
операторов более низкий приоритет, чем у операторов сравнения; среди
них not имеет самый высокий приоритет, а or самый низкий, так что
A and not B or C есть эквивалент (A and (not B)) or C. Как всегда? скобки могут
быть использованы для указания желаемой последовательности выполнения.
Логические операторы and и or являются так называемыми операто­рами short-circuit (короткое замыкание): их аргументы оцениваются слева на
право, и оценка останавливается, как только результат определен. Например,
если A и C являются правдой, но B является ложью, то A and B and C не оценивает выражение C. При использовании не логического значения
возвращаемым значением оператора короткого замыкания является последний
аргумент, который был оценен.
Есть возможность присвоить результат сравнения или другого
логического выражения переменной. Пример
string1, string2, string3 = '', 'Trondheim', 'Hammer Dance' # string1 пустая строка non_null = string1 or string2 or string3 # поиск первой не пустой строки print(non_null) Результат: 'Trondheim'
5.7. Сравнение последовательностей и других типов
Объекты последовательностей могут сравниваться с другими объектами
того же типа. При сравнении используется лексикографический порядок:
сначала сравниваются первые два элемента;
если они разные, то они и определяют результат сравнения;
если они равны, сравниваются следующие два элемента и т. д., пока
одна из двух последовательностей не будет исчерпана.
Если два сравниваемых элемента сами являются последовательностями одного типа, то лексикографическое сравнение осуществляется рекурсивно.
71
Если все элементы последовательностей равны, то последовательности счита-
ются равными. Если одна последовательность совпадает с началом другой, более короткая последовательность считается меньшей. Лексикографический
порядок для строк использует численный код Unicode для сравнения отдельных символов.
Примеры
(1, 2, 3) < (1, 2, 4) [1, 2, 3] < [1, 2, 4] 'ABC' < 'C' < 'Pascal' < 'Python' (1, 2, 3, 4) < (1, 2, 4) (1, 2) < (1, 2, -1) (1, 2, 3) == (1.0, 2.0, 3.0) (1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
Сравнение объектов различных типов с помощью < или > является
законным при условии, что объекты имеют соответствующие методы сравнения. Например, смешанные числовые типы сравниваются в соответствии с их числовым значением, так 0 равен 0.0 и т. д. Когда сравнение невозможно, интерпретатор не обеспечивает случайный порядок, а возбуждает исключение
TypeError.
6. МОДУЛИ
При выходе из интерпретатора Python и входе в него снова определения (функции и переменные), которые были сделаны в предыдущем сеансе, теряются. Следовательно, если вы хотите написать какую-нибудь более длинную программу, вам лучше использовать текстовый редактор для подго­товки ввода для интерпретатора и передать код из этого файла в качестве
входных данных. Это называется созданием скриптов. Когда ваша программа становится длиннее, вы можете захотеть разделить ее на несколько файлов для
более легкого сопровождения. Вы также можете захотеть использовать удоб-
ную написанную вами функцию в нескольких программах без копирования ее
определения в каждую программу.
Для поддержки этого в Python есть способ поместить определения в файл
и использовать их в скриптах или в интерактивном режиме интерпретатора. Такой файл называется модулем; определения из модуля могут быть
импортированы в другие модули или в главный модуль.
Модуль – это файл, содержащий определения и операторы Python.
72
6.1. Подробнее о модулях
Наряду с определениями функций модули могут содержать исполняемые операторы. Эти операторы предназначены для инициализации модуля. Они выполняются только однажды, когда в операторе импорта встречается имя
модуля (Они также запускаются, если файл выполняется как скрипт.).
Каждый модуль имеет его собственную приватную таблицу имен, которая используется как глобальная всеми функциями, определенными в
модуле. Поэтому разработчик модуля, с одной стороны, может использовать
глобальную переменную в модуле без беспокойства о случайном конфликте с глобальными переменными пользователя. С другой стороны, если вы знаете, что делаете, то можете использовать глобальную переменную модуля с такой
же нотацией, которая используется для ссылки на его функцию,
modname.itemname.
Модули могут импортировать другие модули. Принято, но не является
необходимым, размещать все операторы import в начале модуля (это касается и
скрипта). Имя импортируемого модуля помещается в глобальную таблицу имен
импортирующего модуля.
Самый простой способ импортировать модуль в Python – это воспользо­ваться конструкцией:
import имя_модуля.
За один раз можно импортировать сразу несколько модулей, для этого их
нужно перечислить через запятую после слова import :
import имя_модуля1, имя_модуля2.
Если вы хотите задать псевдоним для модуля в вашей программе, можно воспользоваться вот таким синтаксисом:
import имя_модуля as новое_имя.
Пример
import math as m print(m.sin(m.pi / 3 ))
Результат: 0.866025403784438
Используя любой из вышеперечисленных подходов, при вызове функции
из импортированного модуля, всегда необходимо указывать имя модуля (или псевдоним). Для того, чтобы этого избежать для импорта используют кон­струкцию from … import
from имя_модуля import имя_объекта.
Пример
from math import cos print(cos( 3.14 )) Результат: 0.999998731727539
73
Для импортирования нескольких функций из модуля, можно перечислить
их имена через запятую:
from имя_модуля import имя_объекта1, имя_объекта2
Пример
from math import cos, sin, pi print(cos(pi / 3 ))
0.500000000000000 >>> sin(pi / 3 )
Результат: 0.866025403784438
Импортируемому объекту можно задать псевдоним.
from имя_модуля import имя_объекта as псевдоним_объекта
Пример
from math import factorial as f print(f( 4 ))
Результат: 24
Если необходимо импортировать все функции, классы и т. п. из модуля, то следует воспользоваться формой оператора from … import …
from имя_модуля import *
Пример from math import * print(cos(pi / 2 )) Результат: 6.123233995736766e-17
print(sin(pi / 4 )) Результат: 0.707106781186547
print(factorial( 6 )) Результат: 720
6.2. Стандартные модули
Python поставляется с библиотекой стандартных модулей, описанных в отдельном документе, Справка по библиотеке Python. Несколько модулей
встроено в интерпретатор; они предоставляют доступ к операциям, которые не являются частью ядра языка, но тем не менее встроены в него, либо для повышения эффективности, либо для обеспечения доступа к примитивам операционной системы, таким как системные вызовы. Установка таких модулей является конфигурационной опцией, которая также зависит от используемой
платформы. Например, модуль winreg предоставляется только на системах Windows. Один особый модуль заслуживает внимания: sys, который встроен в каждый интерпретатор Python. Переменные sys.ps1 и sys.ps2 определяют стро­ки, используемые как первичное (>>>) и вторичное (…) приглашения.
74
Примеры >>> import sys # подключение библиотеки sys
>>> sys.ps1 # вывод первичного приглашения Результат: '>>> ' >>> sys.ps2 # вывод вторичного приглашения Результат: '... ' >>> sys.ps1 = 'C> ' # Смена первичного приглашения на C> C> print('Yuck!') Yuck! C>
Эти две переменные определены, только если интерпретатор находится в
интерактивном режиме.
Переменная sys.path является списком строк, который определяет путь
поиска модулей интерпретатора. Он инициируется путем по умолчанию, взятым из переменной окружения, или из встроенного по умолчанию, если
PYTHONPATH не установлена. При необходимости можно изменить ее, используя стандартный список операций.
Пример
>>> import sys >>> sys.path.append('/ufs/guido/lib/python')
6.3. Функция dir()
Функция dir() используется для выяснения определенных имен модулей. Она возвращает отсортированный список строк:
>>> import sys >>> dir(sys) Результат: ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getde­faultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount', 'get­trace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions']
75
Без аргументов dir() перечисляет имена, которые были определены в те­кущем сеансе.
Пример
>>> a = [1, 2, 3, 4, 5] >>> import fibo >>> fib = fibo.fib >>> dir()
Результат: ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
В рассмотренном примере перечисляются все типы имен: переменные, модули, функции и т. д. Причем, dir() не перечисляет имена встроенных функ­ций и переменных. Для получения списка имен встроенных функций и пере­менных необходимо подключить стандартный модуль builtins (docs.python.
org/3/library/builtins.html#module-builtins). Пример >>> import builtins
>>> dir(builtins) Результат: ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProces­sError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedEr­ror', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'com­pile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
76
6.4. Пакеты
Пакет в Python – это каталог, включающий в себя другие каталоги и мо­дули, но при этом дополнительно содержащий файл _init__.py. Пакеты исполь­зуются для формирования пространства имен, что позволяет работать с моду­лями через указание уровня вложенности (через точку).
Для импортирования пакетов используется тот же синтаксис, что и для работы с модулями.
Использование пакетов в Python.
Пример структуры пакета
fincalc |-- _init__.py |-- simper.py |-- compper.py |-- annuity.py
Пакет fincal содержит в себе модули для работы с простыми процентами (simper.py ), сложными процентами ( compper.py ) и аннуитетами ( annuity.py ).
Для использования функции из модуля работы с простыми процентами можно использовать один из следующих вариантов:
import fincalc.simper fv = fincalc.simper.fv(pv, i, n) import fincalc.simper as sp fv = sp.fv(pv, i, n) from fincalc import simper fv = simper.fv(pv, i, n)
Файл _init__.py может быть пустым или может содержать переменную _all__, хранящую список модулей, который импортируется при загрузке через
конструкцию:
from имя_пакета import *
Для рассмотренного примера содержимое _init__.py может быть вот та­ким: __all__ = [ "simper" , "compper" , "annuity" ]
При разработке коллекции модулей ("пакет") для единообразной обработки звуковых файлов и звуковых данных, хранящихся во множестве
различных форматов звуковых файлов (обычно распознаваемых по их
расширению, например: .wav, .aiff, .au), потребуется создавать и поддерживать
растущую коллекцию модулей для конверсии между различными форматами файлов. Есть также множество различных операций, которые можно выполнять над звуковыми данными (такие как смешивание, добавление эхо, применение
функции эквалайзера, создание искусственного стерео-эффекта), поэтому в дополнение необходимо писать нескончаемый поток модулей для выполнения
77
этих операций. Здесь возможная структура для вашего пакета (выраженная в
терминах иерархической файловой системы). Пример sound/ Пакет верхнего уровня
__init__.py Инициализирует звуковой пакет formats/ Подпакет для конверсии файловых форматов __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ Подпакет для звуковых эффектов __init__.py echo.py surround.py reverse.py ... filters/ Подпакет для фильтров __init__.py equalizer.py vocoder.py karaoke.py ...
При импорте пакета Python просматривает каталоги в соответствии с sys.path для обнаружания подкаталога пакета.
Файлы __init__.py требуются для того, чтобы Python обрабатывал ката­логи, как содержащие пакеты; это делается для предотвращения, что каталоги с обычными именами, такими как string, не будут непреднамеренно скрывать
действительные модули, которые обнаружатся позже по пути поиска модулей.
В самом простом случае __init__.py может просто быть пустым файлом, но он
также может выполнять инициализирующий код для пакета или устанавливать
переменную __all__, описанную позже.
Пользователи пакета могут импортировать индивидуальные модули из
пакета, например:
import sound.effects.echo.
Загружается подмодуль sound.effects.echo. На него надо ссылаться по его полному имени:
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
Альтернативный способ импорта подмодуля:
78
from sound.effects import echo
Также загружается подмодуль echo, но он доступен без его пакетного префикса, поэтому он может быть использован так:
echo.echofilter(input, output, delay=0.7, atten=4)
Еще одним вариантом является непосредственный импорт нужной
функции или переменной:
from sound.effects.echo import echofilter
Опять же такой импорт загружает подмодуль echo, но это делает его функцию echofilter() доступной напрямую:
echofilter(input, output, delay=0.7, atten=4)
6.5. Импортирование * из пакета
Теперь что случится, когда пользователь напишет sound.effects import *? Хотелось бы надеяться, что в идеале это как-нибудь выходит на файловую
систему, находит, какие подмодули есть в пакете, и импортирует их все. Это может занять долгое время и импортирование подмодулей может иметь нежелательный побочный эффект, который должен происходить только, когда
подмодули явно импортированы.
Для разработчика пакета есть только одно решение обеспечить явное
индексирование пакета. Оператор import использует следующее соглашение: если код __init__.py пакета определяет список под названием __all__, он
берется как список имен модуля, которые должны быть импортированы, когда
встречается from package import *. Разработчик пакета должен обновлять
список, когда выпускается новая версия пакета. Разработчики пакета могут также решить не поддерживать это, если они не видят использования для
импортирования * из их пакета. Например, файл sound/effects/__init__.py может содержать следующий код:
__all__ = ["echo", "surround", "reverse"]
Это бы означало, что from sound.effects import * будет импортировать три названных подмодуля пакета sound.
Если __all__ не определена, выражение from sound.effects import * не импортирует все подмодули из пакета sound.effects в текущее пространство имен; это только обеспечивает то, что пакет sound.effects был импортирован (возможно выполняется какой-нибудь код инициализации из __init__.py) и затем импортирует любые имена, определенные в пакете. Это включает какие­либо имена определенные (и подмодули, загруженные явно) __init__.py. Это также включает какие-либо подмодули пакета, которые были явно загружены предыдущими операторами import. Рассмотрим этот код:
import sound.effects.echo import sound.effects.surround from sound.effects import *
79
В этом примере модули echo и surround импортируются в текущее пространство имен, потому что они определены в пакете sound.effects, когда выполняется выражение from...import (это также работает, когда определена
__all__.)
Хотя некоторые модули разработаны для экспорта только имен, которые
следуют определенным шаблонам, когда вы используете import *, это по­прежнему считается плохой практикой в рабочем коде.
Помните, нет ничего плохого в использовании from Package import
specific_submodule! На самом деле это рекомендованная нотация, если не
требуется из импортируемого модуля использовать подмодули с одинаковыми
именами из различных пакетов.
6.6. Внутрипакетные ссылки
Когда пакеты структурированы в подпакеты (как в пакете sound в примере), можно использовать абсолютные импорты для обращения к подмо­дулям сестринских пакетов. Например, если модулю sound.filters.vocoder надо использовать модуль echo в пакете sound.effects, он может использовать from
sound.effects import echo.
Также можете писать относительные импорты, с формой оператора import from module import name. Такие импорты используют лидирующие точки для указания текущего и родительского пакетов, вовлеченных в относительный
импорт. Например, из модуля surround можно использовать:
from.import echo from..import formats from..filters import equalizer
Относительный импорт основывается на имени текущего модуля. Поскольку имя главного модуля всегда "__main__", модули, предназначенные для использования в качестве главного модуля приложений Python, должны всегда использовать абсолютные импорты.
6.7. Пакеты во множестве директорий
Пакеты поддерживают один более специфический атрибут, __path__. Он инициализируется как список, содержащий имя каталога, хранящего
__init__.py пакета, перед кодом в котором файл выполняется. Эта переменная
может быть изменена; оказывая таким образом влияние на будущий поиск
модулей и подпакетов, включенных в пакет.
Поскольку эта возможность не часто требуется, она может быть исполь­зована для расширения набора модулей, обнаруженных в пакете.
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]