Саммерфилд - Программирование на Python 3 (1077331), страница 65
Текст из файла (страница 65)
Дерево наследования класса ЕсатуВ001 приводится на рис. 6.4. 293 Собственные классы Рис. 6.4. Дерево наследования класса ГиггуВоо( Простейшим логическим оператором является логическое НЕ, в качестве которого мы будем использовать битовый оператор инверсии (-): Оет 1пчегт (ае1().
гетогп гоггуВоо1(!.0 - ае1С ча1пе) Битовый и логический оператор И (Ь) реализуется специальным методом апд (), а соответствующий ему комбинированный оператор присваивания (В=) — методом тапа (): Оет апп (ае1(, о!лег); гетега ГпггуВоо1(в!п(ае1п ча1ое. о!пег, ча1ое)) оет тапа (ае1г, о!пег): ае1(.
ча!пе = а!п(ае1(, ча1пе, о!лег. ча1ое) гетега ае!т Логический оператор И возвращает новый объект гиггуВ001, основываясь на значениях объектов ае1! и о!лег, тогда как комбинированный оператор присваивания изменяет значение частного атрибута. Строго говоря, такое поведение не совсем свойственно неизменяемым объектам, но оно совпадает с поведением некоторых других неизменяемых типов языка Ру!)топ, таких как тп!. Например, при использовании оператора е= создается впечатление, что изменяется операнд слева, но в действительности выполняется перепривязка ссылки на новый объект !пт, хранящий результат операции сложения; хотя в случае гоггуВ001 перепривязку выполнять не требуется, так как мы действительно изменяем сам объект.
Причина, по которой метод возвращает значе- 294 Глава б. Объектно-ориентирозанное программирование нне ве1(, заключается в необходимости обеспечения возможности объ- едннять операции в цепочку. Таблица В.л. Фундаментальные специальные методы Специальный метод Пример использования Описание Ьоо1 (ве1() Если реализован, возвращает значение истинности для х. Удобно, если исполь- зуются конструкции вида тт х. Ьоо1(х) Обеспечивает поддержку метода втг.
гог- евт() для классов "(О)".тогеат(х) тогевт (ве1(, Гогевт врес) Если реализован, х сможет использо- ваться как ключ словаря нлн храниться з множестве палл (ве1() Павп(х) !птт (ве1(, агдв) пен (с1в, агдв) Вызывается прн инициализации объекта х = Х(агдв) х = Х(агдв) Вызывается прн создании объекта Переопределение метода леи (), стр. 300 герг (ве1() герг(х) Возвращает строку с репрезентативной формой представления х, которая обес- печнваетравенстзоечв1(герг(х)) == х авс!1(х) Возвращает строку с ре- М«тод втг. презентатнвной формой пРедставлениЯ х с нс- стр 103 пользованием только символов набора АБСП герг (ве1() втг (ве1() Возвращает строковое представление х, пригодное для восприятия человеком втг(х) Мы могли бы также реализовать метод гапб ().
Этот метод вызывается в случае, когда объекты ве1г н отсег принадлежат разным типам, а метод зпб () для данной пары типов не реализован.' В классе ГизгуВоо1 в этом нет никакой необходимости. Для большннства двухместных операторов имеются специальные методы двух версий: «1» (1п-р1асе — изменяется сам объект) н «г» (ге11есЬ, то есть производится обмен операндов местами). То есть возвращает значение нот!ер1ееептес.
— Прим. перев. Мы не показываем реализации методов сг (), соответствующий логнческому оператору ~, н тог (), соответствующий комбнннрованному оператору присваивания (=, потому что онн полностью эквнвалентны методам реализации операции И, за исключением того, что в результате возвращается не минимальное, а максимальное значение пары ве1( н о(пег. Собственные классы Оет герг (ае1Г): гетогп ("(0)((1))".гогаат(зе1г. о1ааа . паве Мы предусмотрели реализацию метода герг (), воспроизводящего репрезентативную форму представления.
Например, последовательность инструкций т = ЕоагуВоо1. ЕоаяуВоо1(.?5); серг(т) будет воспроизводить строку ' ЕогауВоо1(0. 75) '. Все объекты имеют ряд специальных атрибутов, автоматически создаваемых интерпретатором, один из которых называется с1авв и содержит ссылку на класс объекта. Все классы обладают частным атрибутом паве, который также создается автоматически.
Мы используем зти атрибуты для получения имени класса в репрезентативной форме представления. Это означает, что если от класса ЕоагуВоо1 будет порожден дочерний класс, добавляющий дополнительные методы, унаследованный метод герт () будет продолжать корректно работать и в контексте подкласса, потому что он будет получать имя класса для этого подкласса. Оет атг (ае1Г): гетогп атг(ае1Г.
ха1ое) Специальный метод де! О Специальный метод Ое1 (ае1т) вызывается при уничтожении объекта — по крайней мере в теории. На практике метод Ое1 () может не вызываться никогда, даже при завершении программы. Более того, когда выполняется инструкция Ое1 х, все, что происходит при этом,— удаляется ссылка на объект х и уменьшается счетчик ссылок, указывающих на объект х. Только когда этот счетчик достигает значения О, есть вероятность, что метод Ое1 () будет вызван, но интерпретатор Ру1)топ не дает никаких гарантий, что этот метод будет когда-нибудь вызван.
Но этой причине метод Се1 () очень редко переопределяется — он не переопределяется ни в одном из примеров в этой книге, и он не должен использоваться для освобождения ресурсов, для закрытия файлов, сетевых соединений или подключений к базам данных. Язык РуФ)топ предоставляет два отдельных механизма, при использовании которых можно реализовать корректное освобождение ресурсов. Один из них заключается в использовании блоков тгу ...
т!па11у, как это было показано ранее и как это будет еще показано в главе 7. Другой механизм основан на использовании контекста объекта в соединении с инструкцией н(тл, о которой будет рассказываться в главе 8. Глава б. Объектно-ориентированное программирование 29б Таблица 6.3.Арифметические и битовые специальные методы Специальный метод Специальный метод Пример ис- пользования Пример ис- пользования авв (ве11) 11оат (ве11) !пбех (ве11) аЬв(х) 11оат(х) соар1ех (ве11) !пт,(ве11) гоопб (ве11 б!д! гв) ооар1ех(х) тот(х) гоопб(х, <Гтд! гя) ь!п(х) оот(х) Ьех(х) х-у х -= у у-х хву хв= у ув х 11оогбтн,(ве11, о!Пег) тгиебтч (ве11, о!пег) х/у !11оогб!ч (ве!Г, о1оег) !!греб!ч (ве11, о!Пег) х О= у х /= у гт1оогб!и (ве11, о1пег) гтгоебтч (ве11.
о!Пег) у // х у/х б!чаоб(х, у) бтчаоб(у, х) х а у х ** у х а= у К * у ах у ° ° х К х)у х = у х(=у К у) х х»у х»= у х с< у х с<= у !гво!11 (ве11, Отовг) !1вт(1 (ве11, о!Пег) ггвоттт (ВЕ11, о!Пег) г)втгт (веп, о!Пег) «К у»х !пчегт (ве11) В качестве строковой формы представления мы просто возвращаем значение с плавающей точкой, преобразованное в строку. Мы не использовали функцию ворег(), чтобы избежать попадания в бесконечную рекурсию, и вызываем функцию в1г(), передавая ей атрибут ве1(. ча1ое, а не сам зкземпляр объекта. ров (ве11) абб (ве11, о!Пег) табо (ве11, о!пег) габб (ве11.
о!пег) ао1 (ве11, о!Пег) !ан1 (яе11, о!Пег) гао! (ве1(, о!Пег) бтчаоб (ве11, о1пег) ров (ве11, о1оег) !ров (ве11, о!пег) гров (ве11, о1Пег) хог (ве11, о1пег) !Ког (ве11, о!пег) гхог (ве!Г, о1Пег) 1вт(1 (ве11, о1пег) ха у х а= у у ах х*у к *= у у *х х // у пед (ве11) воо (ве11, о!пег) !явь (ве11, о!пег) гвоо (ве11, о!пег) аоб (ве!1, о1Пег) !аоб (яе11, о!пег) гаоб (ве11, о1Пег) гб!наоб (веп, о1пег) апб (ве11, о!пег) !апб (ве11, о1пег) гапб (ве11, о!пег) ог (ве!1, о!пег) !Ьг (ве11, о!пег) гог (яе11, о!Пег) гвп!11 (ве11, о!пег) Собственные классы 297 Се( Ьоо1 (ве1(); гетогп ве1Г, ча1ое > 0.5 Оет гпт (ве1Г): гетогп гоопз(ве1б ча1ое) Оет (1оат (ве1(): гетогп ве1(. ча1ое Специальный метод Ьсс1 () преобразует экземпляр в тип Ьса1, то есть он всегда должен возвращать либо Тгое, либо Га1ве.
Специальный метод >пт () реализует преобразование в целое число. Мы использовали здесь встроенную функцию гсопб(), потому что функция тпт() просто усекает дробную часть (поэтому для любого значения ЕоагуВсо!, кроме 1.0, метод всегда возвращал бы значение О). Преобразование в число с плавающей точкой выполняется очень просто, потому что само значение уже является числом с плавающей точкой. Оет 11 (ве15, с<пег): гетогп зе1т, ча1ое < стЬег.
ча1ое оег ес (ве1г. стьег): гетогп ве1г, ча1ое == о<пег. ча1ое Чтобы обеспечить полную поддержку всех операторов сравнения («, =, ==, ! =, »=, ), необходимо реализовать хотя бы три из них: «, = и ==, потому что интерпретатор сможет вывести действие оператора > из оператора <,! =— из == и >= — из <5н Мы привели реализацию лишь двух методов, потому что все они очень похожи между собой.' Сот Ьавл (ве1(): гетогп ьавь(гэ(ве11)) По умолчанию экземпляры наших собственных классов поддерживают оператор == (который всегда возвращает Ва1ве) и являются хешируемыми (поэтому они могут использоваться в качестве ключей словаря или добавляться в множества). Но если реализовать специальный метод ез (), выполняющий корректную проверку на равенство, экземпляры перестанут быть хешируемыми. Зто можно исправить, реализовав специальный метод Ьавл (), что мы и сделали.
Язык РуФйоп предоставляет функцию хеширования строк, чисел, фиксированных множеств и других классов. Здесь мы просто воспользовались встроенной функцией Ьавл() (которая может работать с любым типами данных, имеющими специальный метод Ьавл ()) и передаем ей уникальный идентификатор объекта, на основании которого вычисляется хеш-значение.
(Мы не можем использовать частный В действительности мы реализовали лишь два метода, 11 () н ез (), приведенные здесь, — остальные методы сравнения генерируются автоматически, как будет показано в главе 8. 298 Глава 6. Объектно-ориентированное программирование атрибут зе1г. уа1се, потому что он может изменяться комбинированными операторами присваивания, а хеш-значение никогда не должно изменяться.) Встроенная функция 1В() возвращает уникальное целое число для объекта, который передается в виде аргумента. Обычно этим целым числом является адрес объекта в памяти, однако мы можем только предполагать, что в программе не может существовать двух объектов с одинаковыми числовыми идентификаторами. Функция 10() используется внутри реализации оператора 1В, который определяет, указывают ли две ссылки на один и тот же объект. бег гогват (пе1г, гпгват прес): гетигп гогват(пе11.