Python/Объектно-ориентированное программирование на Python: различия между версиями

перенесено из Википедии
(→‎Полиморфизм: орфографическая ошибка в слове polymorphism.)
(перенесено из Википедии)
{{К удалению|2017-01-08}}
'''Объектно-ориентированное программирование на Python''' — программирование на Python с использованием [[парадигма программирования|парадигмы]] [[объектно-ориентированное программирование|ООП]]: с самого начала [[Python]] проектировался как [[объектно-ориентированный язык программирования]]<ref name="python oop from beginning">[http://www.ercb.com/ddj/1997/ddj.9711.html Dr. Dobb’s Journal, November, 1997]</ref>.
 
== Введение ==
 
=== Принципы ООП ===
Согласно [[Кей, Алан|Алану Кэю]]  — автору языка программирования [[Smalltalk]]  — объектно-ориентированным может называться язык, построенный с учетом следующих принципов<ref name="alan kay oop principles">[http://www.cs.aau.dk/~torp/Teaching/E02/OOP/handouts/introduction.pdf Introduction to Object-Oriented Programming]</ref>:
 
* Все данные представляются объектами
pass
</source>
В терминологии Python члены класса называются атрибутами, функции класса  — [[Метод (программирование)|методами]], а [[Поле класса|поля класса]]  — [[Свойство (программирование)|свойствами]] (или просто атрибутами).
 
Определения методов аналогичны определениям функций, но (за некоторыми исключениями, о которых ниже) методы всегда имеют первый аргумент, называемый по общепринятому соглашению <code>self</code>:
# блок кода метода
</source>
Определения [[Атрибут (программирование)|атрибутов]]  — обычные операторы присваивания, которые связывают некоторые значения с именами атрибутов.
<source lang="python">
class A:
 
=== Создание экземпляра ===
Для создания [[Объект (программирование)|объекта]]  — экземпляра класса (то есть, инстанцирования класса), достаточно вызвать класс по имени и задать параметры конструктора:
<source lang="python">
class Point:
Обычно время жизни объекта, определённого в программе на Python, не выходит за рамки времени выполнения процесса этой программы.
 
Для преодоления этого ограничения объект можно сохранить, а после  — восстановить. Как правило, при записи объекта производится его [[сериализация]], а при чтении  — десериализация.
 
<source lang="python">
[[Инкапсуляция (программирование)|Инкапсуляция]] является одним из ключевых понятий ООП. Все значения в Python являются объектами, инкапсулирующими код (методы) и данные и предоставляющими пользователям общедоступный интерфейс. Методы и данные объекта доступны через его атрибуты.
 
Сокрытие информации о внутреннем устройстве объекта выполняется в Python на уровне соглашения между программистами о том, какие атрибуты относятся к общедоступному интерфейсу класса, а какие  — к его внутренней реализации. Одиночное подчеркивание в начале имени атрибута говорит о том, что атрибут не предназначен для использования вне методов класса (или вне функций и классов модуля), однако, атрибут все-таки доступен по этому имени. Два подчеркивания в начале имени дают несколько большую защиту: атрибут перестает быть доступен по этому имени. Последнее используется достаточно редко.
 
Есть существенное отличие между такими атрибутами и личными (private) членами класса в таких языках как [[C++]] или [[Java]]: атрибут остается доступным, но под именем вида <code>_ИмяКласса__ИмяАтрибута</code>, а при каждом обращении <code>Python</code> будет модифицировать имя в зависимости от того, через экземпляр какого класса происходит обращение к атрибуту. Таким образом, родительский и дочерний классы могут иметь атрибут с именем, например, «__f», но не будут мешать друг другу.
Разумеется, первый способ хорош только если значение атрибута является атомарной операцией по изменению состояния объекта. Если же это не так, то второй способ позволит выполнить все необходимые действия в соответствующих методах.
 
Существуют два способа централизованно контролировать доступ к атрибутам. Первый основан на перегрузке методов <code>__getattr__()</code>, <code>__setattr__()</code>, <code>__delattr__()</code>, а второй  — метода <code>__getattribute__()</code> . Второй метод помогает управлять чтением уже существующих атрибутов.
 
Эти способы позволяют организовать полностью динамический доступ к атрибутам объекта или, что используется очень часто, имитации несуществующих атрибутов. По такому принципу функционируют, например, все системы [[Remote Procedure Call|RPC]] для Python, имитируя методы и свойства, реально существующие на удаленном сервере.
его использование, необходимо рассмотреть менее радикальные варианты реализации изменения объекта, то есть по сути шаблона проектирования [[Состояние (шаблон проектирования)|State]].
 
Более того, полиморфизм в Python вообще не связан с наследованием, поэтому его можно считать сигнатурно-ориентированным полиморфизмом (signature-oriented polymorphism)<ref name="signature-oriented polymorfism">[http://lwn.net/2001/1011/a/python-url.php3 в списке рассылки comp.lang.python]</ref>. Например, чтобы экземпляру класса «прикинуться» файловым объектом, ему достаточно реализовать методы, относящиеся к файлам (обычно <code>.read()</code>, <code>.readlines()</code>, <code>.close()</code> и  т.  п.).
 
=== Имитация встроенных типов ===
Встроенные типы и их методы имеют синтаксическую поддержку в языке Python или другие особые «привилегии». Конечно, любая операция может быть представлена синтаксисом вызова функции, однако, для частого применения это неудобно.
 
Воспользоваться точно такой же синтаксической поддержкой может и любой определённый пользователем класс. Для этого нужно лишь реализовать методы со специальными именами. Самый простой пример  — имитировать функцию:
<source lang="python">
>>> class Add:
</source>
 
Последний из методов  — <code>.__str__()</code>  — отвечает за представление экземпляра класса при печати оператором <code>print</code> и в других подобных случаях.
 
Аналогичные методы имеются и у соответствующих встроенных типов:
 
=== Наследование и множественное наследование ===
При описании предметной области классы могут образовывать иерархию, в корне которой стоит базовый класс, а нижележащие классы (подклассы) наследуют свои атрибуты, уточняя и расширяя поведение вышележащего класса (надкласса). Обычно принципом построения классификации является отношение «IS-A» («есть»  — между экземпляром и классом) и «AKO» («a kind of»  — «разновидность»  — между классом и суперклассом)<ref>[[Семантическая сеть#История|«AKO» и «IS-A»]]</ref>.
 
Python поддерживает как одиночное [[наследование (программирование)|наследование]], так и множественное, позволяющее классу быть производным от любого количества базовых классов.
ещё не означает, что объект не может предоставлять тот же самый интерфейс.
 
[[Множественное наследование]] в Python применяется в основном для добавления примесей (mixins)  — специальных классов, вносящих некоторую черту поведения или набор свойств{{sfn|Beazley|2009|pages=122}}.
 
==== Порядок разрешения доступа к методам и полям ====
со старым кодом) и «новые»<ref name="python new style classes">[http://docs.python.org/reference/datamodel.html#new-style-and-classic-classes New-style Classes]</ref>. В версии [[Python3000]] поддержка «старых» классов будет удалена.<br />
Для построения «нового» класса достаточно унаследовать его от другого
«нового». Если нужно создать «чистый» класс, то можно унаследоваться от <code>object</code>  — родительского типа для всех «новых» классов.
<source lang="python">
class OldStyleClass: pass # класс "старого" типа
class NewStyleClass(object): pass # и "нового"
</source>
Все стандартные классы  — классы «нового» типа.<ref>[http://www.python.org/download/releases/2.2.3/descrintro/ Объяснение Гвидо ван Россума об объединении типов и классов]</ref>
 
=== Агрегация. Контейнеры. Итераторы ===
 
=== Метаклассы ===
Обычных возможностей объектно-ориентированного программирования хватает далеко не всегда. В некоторых случаях требуется изменить сам характер системы классов: расширить язык новыми типами классов, изменить стиль взаимодействия между классами и окружением, добавить некоторые дополнительные аспекты, затрагивающие все используемые в приложении классы, и  т.  п.
 
При объявлении метакласса за основу можно взять класс <code>type</code>. Пример:
myobj = MySubObject("parameter")
</source>
Разумеется, вместо оператора <code>print</code> код метакласса может выполнять более полезные функции: регистрировать класс, передавать действия с классами на удаленную систему, использовать классы для других целей (например, как декларации или ограничения) и  т.  п.
 
== Методы ==
</source>
 
Получаемая при сериализации строка может быть передана по сети, записана в файл или специальное хранилище объектов, а позже  — прочитана. Сериализации поддаются не все объекты. Некоторые объекты (например, классы и функции) представляются своими именами, поэтому для десериализации требуется наличие тех же самых классов. Нужно отметить, что нельзя десериализовать данные из непроверенных
источников с помощью модуля <code>pickle</code>, так как при этом возможны практически любые
действия на локальной системе. При необходимости обмениваться данными по незащищенным каналам
или с ненадежными источниками можно воспользоваться другими модулями для сериализации.
 
В основе сериализации объекта стоит представление его состояния. По умолчанию состояние объекта  — это все, что записано в его полях. Пользовательские классы могут управлять сериализацией, предоставляя состояние объекта явным образом (методы <code>__getstate__</code>, <code>__setstate__</code> и др.).
 
На стандартном для Python механизме сериализации построена работа модуля <code>shelve</code> (shelve (англ. глаг.)  — ставить на полку; сдавать в архив). Модуль предоставляет функцию
<code>open</code>. Объект, который она возвращает, работает аналогично словарю, но объекты сериализуются и сохраняются в файле:
 
</source>
 
Сериализация <code>pickle</code>  — не единственная возможная, и подходит не всегда. Для сериализации, не зависящей от языка программирования, можно использовать, например, XML.
 
== Примечания ==
* {{книга|автор=David M. Beazley|заглавие=Python Essential Reference|издание=4th Edition|год=2009|издательство=Addison-Wesley Professional|страниц=717|isbn=978-0672329784|ref=Beazley}}
 
[[Категория:Python (язык программирования)]]
== Ссылки ==
 
{{rq|refless|renew}}
 
[[Категория:Объектно-ориентированное программирование]]
[[Категория:Python]]
[[Категория:Статьи с примерами кода Python]]
282

правки