Лутц М. - Изучаем Python (1077325), страница 120
Текст из файла (страница 120)
Напишите второй модуль тусйеппру, который импортирует модуль пупов и проверяет работу его функций, затем запустите зус1гепГ из системной командной строки. Будут ли доступны функции из зувос на верхнем уровне аус11епг, если импортировать их с помощью инструкции Г гоп"г А если они будут импортированы с помощью инструкции шроггу Попробуйте реализовать оба варианта в аус11епг и проверить в интерактивном режиме, импортируя модулыус11Епт и проверяя содержимое его атрибута о1сГ Импорт пакетов.
Импортируйте ваш файл из пакета. Создайте каталог с именем тур)гд, вложенный в каталог, находящийся в пути поиска модулей. Переместите в него файл тутог!.ру, созданный Глава 21. Дополнительные возможности модулей в упражнении 1 или 3, и попробуйте импортировать его как пакет, инструкцией тзрогт зурнб.зувос. Вам потребуется добавить файл 1л11 .ру в каталог, куда был помещен ваш модуль. Это упражнение должно работать на всех основных платформах РуС)топ (это одна из причин, почему в языке РуФЬоп в качестве разделителя компонентов пути используется символ». »). Каталог пакета может быть простым подкаталогом в вашем рабочем каталоге — в этом случае он будет обнаружен интерпретатором при поиске в домашнем каталоге и вам не потребуется настраивать путь поиска.
Добавьте какой-нибудь программный код в тлй .ру и посмотрите, будет ли он выполняться при каждой операции импортирования. 6. Повторная загрузка. Поэкспериментируйте с возможностью повторной загрузки модуля: выполните тесты, которые приводятся в примере с)запИегру в главе 19, многократно изменяя текст сообщения и/или поведение модуля, без остановки интерактивного сеанса работы с интерпретатором РуФЬоп. В зависимости от операционной системы файл модуля можно было бы редактировать в другом окне или, приостановив интерпретатор, редактировать модуль в том же окне (в 1)М1Х комбинация клавиш С$г1-2 обычно приводит к приостановке текущего процесса, а команда Гб — возобновляет его работу).
7. Циклический импорт.' В разделе, где описываются проблемы, связанные с рекурсивным импортом, импортирование модуля гесогт вызывает появление ошибки. Но если перезапустить интерактивный сеанс работы с интерпретатором и предварительно импортировать модуль гесс г2, ошибка не возникает — проверьте этот факт сами. Как вы думаете, почему импортирование гессг2 проходит без ошибок, а импортирование гесог1 с ошибками7 (Подсказка: интерпретатор РуФЬоп сохраняет новые модули во встроенной таблице (словаре) зуз, вобс1ез перед их запуском, независимо от того, »завершен» модуль или нет.) Теперь попробуйте запустить гесс г1 как самостоятельный сценарий: рутвол гессг1. ру. Получите ли вы ту же самую ошибку, которая возникает при импортировании гесс г1 в интерактивной оболочке? Почему7 (Подсказка: когда модули запускаются как самостоятельные программы, они ие импортируются, поэтому здесь возникает тот же эффект, как и при импортировании гесс г2 в интерактивной оболочке, — гесс г2 является первым импортируемым модулем.) Что произойдет, если запустить гесог2 как самостоятельный сценарий 2 Почему2 Обратите внимание, что циклическое импортирование чрезвычайно редко встречается на практике.
Автор этой книги за десять лет работы с языком РуФЬоп на практике сам не использовал и не сталкивался с циклическим импортом. Однако если вы в состоянии понять, в чем заключается проблема прв использовании циклического импорта, это будет означать, что вы достаточно много знаете о семантике языка Рут)топ. Классы и ООП ООП: общая картина До сих пор в этой книге мы использовали термин»объект» в общем смысле. В действительности весь программный код, написанный нами до сих пор, был основан на объектах (оЬ/есг-Ьазей) — везде в своих сценариях мы передавали объекты, использовали их в выражениях, вызывали их методы и т. д. Однако, чтобы наш программный код стал по-настоящему объектно-ориентированным (оЬ|есбог(еягео, ОО), наши объекты должны участвовать в иерархии наследования.
Начиная с этой главы, мы приступаем к исследованию классов в языке РуФпоп — программных компонентов, используемых для реализации новых типов объектов, поддерживающих наследование. Классы— это основные инструменты объектно-ориентированного программирования (ООП) в языке РуФЬоп, поэтому в этой части книги мы попутно рассмотрим основы ООП. ООП предлагает другой, часто более эффективный подход к программированию, при котором мы разлагаем программный код на составляющие, чтобы снизить его избыточность, и пишем новые программы, адаптируя имеющийся программный код, а не изменяя существующий или создавая новый код.
Классы в языке Ру1)»оп создаются с помощью новой для нас инструкции: инструкции с1азз. Как вы увидите, объекты, определяемые с помощью классов, очень напоминают встроенные типы, которые мы изучали ранее в этой книге. В действительности классы лишь применяют и дополняют понятия, которые мы уже рассмотрели. Грубо говоря— они представляют собой пакеты функций, которые в основном используют и обрабатывают объекты встроенных типов. Основное назначение классов состоит в том, чтобы создавать и манипулировать новыми объектами, а кроме того, они поддерживают механизм наследования— совсем иной способ адаптации программного кода и повторного его использования, чем мы рассматривали ранее. Глава 22, ООП: общая картина 562 Одно предварительное замечание: ООП в языке Ру$Ьоп является необязательным к применению, и на первых порах вам не обязательно использовать классы.
Многие задачи можно реализовать с помощью более простых конструкций, таких как функции, или даже просто программируя на верхнем уровне в сценарии. Поскольку использование классов требует некоторого предварительного планирования, они представляют больший интерес для тех, кто работает в стратегическом режиме (участвует в долгосрочной разработке программных продуктов), чем для тех, кто работает в тактическом режиме (где на разработку дается очень короткое время). Однако, как вы увидите в этой части книги, классы являются одним из самых мощных инструментов в языке Ругпоп. При грамотном использовании классы способны радикально сократить время, затрачиваемое на разработку.
Они также присутствуют в таких популярных инструментах, как Тх(п$ег СШ АР1, поэтому для большинства программистов, использующих язык РуФЬоп, знание основ работы с классами будет как минимум полезно. Зачем нужны классы? Помните, как я говорил вам, что «программы выполняют некоторые действия над чем-то»2 Проще говоря, классы — это всего лишь способ определить новое «что-то», они являются отражением реальных объектов в мире программ.
Например, предположим, что мы решили реализовать гипотетическую машину по изготовлению пиццы, которую мы использовали в качестве примера в главе 15. Если реализовать ее на основе классов, мы могли бы смоделировать более близкое к реальности строение машины и взаимосвязь между ее механизмами. Полезными здесь оказываются два аспекта ООП; Наследование Машина по изготовлению пиццы — это разновидность машин, поэтому она обладает обычными свойствами, характерными для машин. В терминах ООП это называется «наследованием» свойств более общей категории машин. Эти общие свойства необходимо реализовать всего один раз, после чего мы сможем использовать их для моделирования любых типов машин, которые нам потребуется создать в будущем. Композиция Машины по изготовлению пиццы состоят из множества компонентов, которые все вместе работают как единое целое.
Например, нашей машине необходимы манипуляторы, чтобы раскатывать тесто, двигатели, чтобы перемещаться к духовке, и т. д. На языке ООП наша машина — это пример композиции; она содержит другие объекты, которые активизируются для выполнения определенных дейст- Зачем нужны классы? 563 вий. Каждый компонент может быть оформлен как класс, который определяет свое поведение и принципы взаимодействия. Общие идеи ООП, такие как наследование и композиция, применимы к любым приложениям, которые могут быть разложены на ряд объектов.
Например, в типичных программах с графическим интерфейсом сам интерфейс создается как набор визуальных элементов управления— кнопок, меток и т. д., которые рисуются на экране в тот момент, когда выполняется рисование их контейнеров (композиция). Кроме того, мы можем создать свои собственные визуальные элементы — кнопки с уникальными шрифтами, метки с новыми цветовыми схемами, которые будут представлять собой специализированные версии более общих интерфейсных элементов (наследование). Если говорить более точно, с точки зрения программирования классы— это программные компоненты на языке РуФпоп, точно такие же, как функции и модули: они представляют собой еще один способ упаковки выполняемого кода и данных.
Кроме того, классы определяют свои пространства имен, так же как и модули. Но в отличие от других программных компонентов, которые мы уже видели, классы имеют три важных отличия, которые делают их более полезными, когда дело доходит до создания новых объектов: Множество экземпляров Классы по своей сути являются фабриками по созданию объектов. Каждый раз, когда вызывается класс, создается новый объект со своим собственным пространством имен. Каждый объект, созданный из класса, имеет доступ к атрибутам класса и получает в свое распоряжение собственное пространство имен для своих собственных данных, отличных от данных других объектов.
Адаптация через наследование Классы также поддерживают такое понятие ООП, как наследование, — мы можем расширять возможности класса, переопределяя его атрибуты за пределами самого класса. В более общем смысле классы могут создавать иерархии пространств имен, которые определяют имена для использования объектами, созданными из классов в иерархии. Перегрузка опера т орое Обеспечивая специальный протокол оформления методов, классы могут определять объекты, над которыми можно производить какие-то из операций, которые мы знаем по работе со встроенными типами. Например, объекты, созданные из классов, могут подвергаться операции извлечения среза, конкатенации, извлечения элементов по их индексам и т.