Лутц М. - Изучаем Python (1077325), страница 148
Текст из файла (страница 148)
После этого вложенный метод ее(боб Этот пример будет работать в версии РуФ)топ 2.2 и выше, потому что все локальные области вмещающих функций автоматически видимы для вложенных функций (включая и вложенные методы, как в данном примере). Но он не работал в версиях РуФЬоп, вышедших до версии 2.2 (некоторые возможные решения приводятся ниже). Обратите внимание, что даже в версии 2.2 методам недоступна локальная область видимости вмещающего класса — им доступны только области видимости вмещающих функций.
Именно по этой причине методы должны использовать аргумент ве11 с экземпляром или имя класса, чтобы вызывать другие методы или обращаться к другим атрибутам, определенным во вмещающей инструкции с1авв. Например, программный код метода не может использовать простое имя сопят, он должен использовать имя вв!1. соил( или Брав, сопит. 689 Типичные проблемы при работе с классами и функция депе гаге будут отыскивать класс Брав в глобальной области видимости: Оет делегате(): гешгп Брав() а Определение на верхнем уРовне в модуле с1авв Брав: сопят = 1 оет ~яетпоо(ве1(): ргтпт Брав.сосет В Работает: глобал~нов имя (вмещающий модуль) депегасе().щеюоо() В действительности такой подход рекомендуется использовать во всех версиях РувЬоп — программный код выглядит проще, если в нем отсутствуют вложенные классы и функции. Если вам требуется нечто более сложное и замысловатое, то можно просто избавиться от ссылки на имя Брав в методе щетаоб, используя специальный атрибут с1авв, который возвращает класс объекта экземпляра: Оет депегате(): с1авв Брав: соопт = 1 бег щетпоб(ве1().' ргнп ве)т.
с1авв .соопт в Работает: используется атрибут гетсгп Брав() В для получения класса депегате().щетпос() «Многослойное обертывание» При грамотном использовании способность объектно-ориентированного программного кода к многократному использованию поможет существенно снизить затраты времени на его разработку. Однако иногда неправильное использование потенциала абстракции ООП может серьезно осложнить понимание программного кода. Если классы наслоены друг на друга слишком глубоко, программный код становится малопонятным — возможно, вам придется изучить множество классов, чтобы выяснить, что делает единственная операция. Например, однажды мне пришлось работать с библиотекой, написанной на языке С++, содержащей тысячи классов (часть которых была сгенерирована машиной) и до 1б уровней наследования. Расшифровка вызовов методов в такой сложной системе классов часто оказывалась неподъемной задачей: даже в простейшую операцию оказывались вовлеченными сразу несколько классов.
Логика системы оказалась такой многослойной, что в некоторых случаях, чтобы понять принцип действия какого-либо участка программного кода, требовалось несколько дней копаться в нескольких файлах. Здесь также вполне применимо одно из самых универсальных правил языка РувЬоп: не усложняйте решение задачи, если оно не является 690 Глава 26.
Дополнительные возможности классов таковым. Обертывание программного кода несколькими слоями классов на грани непостижимости — всегда плохая иден. Абстракция — это основа полиморфизма и инкапсуляции, и при грамотном использовании она может быть весьма эффективным инструментом. Однако вы упростите отладку и сопровождение, если сделаете интерфейсы своих классов интуитивно понятными. Избегайте чрезмерной абстракции и сохраняйте иерархии своих классов короткими и плоскими, если не существует веских причин сделать иначе. В заключение Б этой главе было представлено несколько расширенных возможностей классов, включая наследование встроенных типов, псевдочастные атрибуты, классы нового стиля, статические методы и декораторы функций. Большинство из них являются необязательными расширениями модели ООП в языке Руслоп, но они могут стать более полезными, когда вы начнете создавать крупные объектно-ориентированные программы.
Это конец части, посвященной классам, поэтому ниже вы найдете обычные в этом случае упражнения — обязательно проработайте их, чтобы получить некоторую практику создания настоящих классов. Б следующей главе мы начнем изучение последней базовой темы — исключений. Исключения — это механизм взаимодействий с ошибками и другимн ситуациями, возникающими в программном коде. Это относительно несложная тема, но я оставил ее напоследок, потому что в настоящее время исключения оформлены в виде классов.
Но прежде чем заняться этой последней темой, ознакомьтесь с контрольными вопросами к этой главе и выполните упражнения. Закрепление пройденного Контрольные вопросы 1. Назовите два способа расширения встроенных типов. 2. Для чего используются декораторы функций7 3. Как создать класс нового стиля? 4. Чем отличаются классы нового стиля и классические классы7 5. Чем отличаются обычные и статические методы7 б.
Сколько секунд нужно выждать, прежде чем бросить «Пресвятую ручную гранату» 7 Ответы 1. Можно заключать встроенные классы в классы-обертки или наследовать встроенные типы в подклассах. Последний вариант проще, так как в этом случае подклассы наследуют большую часть поведения оригинальных классов. б91 Закрепление пройденного 2.
Декораторы функций обычно используются для добавления дополнительного слоя логики к существующим функциям, который запускается при каждом вызове функции. Они могут использоваться для регистрации вызовов этих функций, проверки типов передаваемых аргументов и т. д. Кроме того, они используются для «объявления» статических методов — простых функций в классе„которым не передается экземпляр класса. 3. Классы нового стиля создаются наследованием встроенного класса оо)есг (или любого другого встроенного типа). В РуФпоп 3«0 все классы по умолчанию будут классами нового стиля. 4.
При использовании ромбоидальной схемы наследования в классах нового стиля поиск в дереве наследования выполняется иначе — сначала производится поиск в ширину, а не в высоту. Кроме того, классы нового стиля поддерживают ряд новых дополнительных особенностей, включая свойства и список атрибутов экземпляра з1огз 5. Обычные методы (экземпляра) принимают аргумент эе1( (подразумеваемый экземпляр), а статические методы — нет. Статические методы — это простые функции, вложенные в объект класса. Чтобы превратить обычный метод в статический, необходимо передать его специальной встроенной функции, или декоратору, с использованием правил декорирования. 6. 'Гри секунды. (Или, если быть более точным: «И сказал Господь: Допреже всего Пресвятую чеку извлечь долженствует.
Опосля же того, сочти до трех, не более и не менее. Три есть цифирь, до коей счесть потребно, и сочтенья твои суть три. До четырех счесть не моги, паче же до двух, опричь токмо коли два предшествует трем. О пяти и речи быть не может. Аще же достигнешь ты цифири три, что есть и пребудет третьею цифирью, брось Пресвятою антиохийскою гранатою твоею во врага твоего, и оный враг, будучи ничтожен пред лицем моим, падет. » ').
Упражнения к шестой части В этих упражнениях вам будет предложено написать несколько классов и поэкспериментировать с существующим программным кодом. Единственная проблема существующего кода состоит в том, что он должен существовать. Чтобы поупражняться с набором классов в упражнении 5, вам нужно либо загрузить файл с исходными текстами из Интернета (читайте Предисловие) или ввести его вручную (он достаточно короткий). Поскольку программы становятся все сложнее, обязательно ознакомьтесь с решениями в конце книги. Решения вы найдете в приложении В в разделе «Часть Ч1. Классы и ООП». Цитата нэ фильма «Моп!у Ру!Ьоп ап«! ФЬе Но!у Сга!1».
Перевод взят из Викнпедни. В русском переводе фильм вышел под названием «Монти Пайтон н Священный Грааль». — Примеч. перев. 692 Глава 26. Дополнительные воэможности классов 1. Наследоеание. Напишите класс е именем Аббег, экспортирующий метод абб(ве1(, х, у), который выводит сообщение «Хо$1тпр1етепФ- ес)» («Не реализовано»). Затем определите два подкласса класса Аббес, которые реализуют метод абб: ~твтАббег С методом абб, который возвращает результат конкатенации двух списков из аргументов.
ОтетАббег С методом абб, который возвращает новый словарь, содержащий элементы из обоих словарей, передаваемых как аргументы (подойдет любое определение сложения). Поэкспериментируйте с экземплярами всех трех классов в интерактивной оболочке, вызывая их методы абб. Теперь расширьте суперкласс Аббег, добавив сохранение объекта в экземпляре с помощью конструктора (например, присваивая список или словарь атрибуту ве1(, бата), и реализуйте перегрузку оператора + с помощью метода абб так, чтобы он автоматически вызывал ваш метод абб (например, выражение Х + У должно приводить к вызову метода Х.абб(Х.бата, у)).