Объектно-ориентированный Python
Python был объектно-ориентированным языком с момента его создания. Благодаря этому очень легко создавать классы и объекты в Python. В этой главе мы подробно рассмотрим объектно-ориентированное программирование в Python.
Если вы ранее не сталкивались с объектно-ориентированными языками программирования, возможно, вам нужно сначала понять некоторые основные особенности объектно-ориентированных языков и сформировать в уме базовое представление об объектной ориентации, что поможет вам легче изучить объектно-ориентированное программирование в Python.
Далее давайте кратко рассмотрим некоторые основные особенности объектной ориентации.
Введение в объектно-ориентированную технологию
- Класс:Используется для описания набора объектов с одинаковыми атрибутами и методами. Он определяет атрибуты и методы, общие для каждого объекта в наборе. Объекты являются экземплярами классов.
- Переменная класса:Переменные класса являются общими для всех экземпляров объектов. Переменные класса определяются внутри класса и вне любого тела функции. Переменные класса обычно не используются в качестве переменных экземпляра.
- Члены данных:Переменные класса или переменные экземпляра, используемые для обработки данных, связанных с классом и его объектами-экземплярами.
- Переопределение метода:Если метод, унаследованный от родительского класса, не может удовлетворить потребности дочернего класса, его можно переписать. Этот процесс называется переопределением метода.
- Локальные переменные:Переменные, определенные в методах, влияющие только на класс текущего экземпляра.
- Переменные экземпляра:В объявлении класса атрибуты представлены переменными. Такие переменные называются переменными экземпляра, объявленными внутри объявления класса, но вне других методов-членов класса.
- Наследование:То есть производный класс наследует поля и методы базового класса. Наследование также позволяет объекту производного класса рассматриваться как объект базового класса. Например, есть проект: объект типа Dog является производным от класса Animal, что имитирует отношение «is-a» (например, Dog — это Animal).
- Инстанцирование:Создание экземпляра класса, конкретного объекта класса.
- Метод:Функция, определённая в классе.
- Объект:Экземпляр структуры данных, определённой классом. Объекты включают два члена данных (переменные класса и переменные экземпляра) и методы.
Создание классов
Используйте инструкцию class для создания нового класса. После class идёт имя класса, и строка заканчивается двоеточием:
class ClassName: '类的帮助信息' #类文档字符串 class_suite #类体
Справочную информацию о классе можно посмотреть с помощью ClassName.__doc__.
class_suite состоит из членов класса, методов и атрибутов данных.
Пример
Ниже приведён простой пример класса Python:
Пример
Переменная empCount — это переменная класса, значение которой совместно используется всеми экземплярами этого класса. Доступ к ней можно получить через Employee.empCount внутри класса или из внешнего класса.
Первый метод, __init__(), — это специальный метод, называемый конструктором класса или методом инициализации. Этот метод вызывается при создании экземпляра класса.
self представляет экземпляр класса. self требуется при определении методов класса, хотя соответствующий параметр не нужно передавать при вызове.
self представляет экземпляр класса, а не сам класс
Методы класса имеют только одно особое отличие от обычных функций — они должны иметь дополнительноеимя первого параметра, по соглашению его имя — self.
Результат выполнения приведенного выше примера:
<__main__.Test instance at 0x10d066878> __main__.Test
Из результата выполнения совершенно ясно, что self представляет экземпляр класса, представляя адрес текущего объекта, тогда какself.__class__указывает на класс.
self не является ключевым словом Python. Мы можем заменить его на example, и это всё равно будет нормально выполняться:
Пример
Результат выполнения приведенного выше примера:
<__main__.Test instance at 0x10d066878> __main__.Test
Создание экземпляров объектов
При создании экземпляра класса другие языки программирования обычно используют ключевое слово new, но в Python такого ключевого слова не существует. Создание экземпляра класса похоже на вызов функции.
Ниже для создания экземпляра используется имя класса Employee, а параметры принимаются через метод __init__.
"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
Доступ к атрибутам
Вы можете использовать точку.для доступа к атрибутам объекта. Чтобы обратиться к переменным класса, используйте имя класса следующим образом:
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
Полный пример:
Пример
Результат выполнения приведённого выше кода выглядит следующим образом:
Name : Zara ,Salary: 2000 Name : Manni ,Salary: 5000 Total Employee 2
Вы можете добавлять, удалять и изменять атрибуты класса, как показано ниже:
emp1.age = 7 # 添加一个 'age' 属性 emp1.age = 8 # 修改 'age' 属性 del emp1.age # 删除 'age' 属性
Вы также можете использовать следующие функции для доступа к атрибутам:
- getattr(obj, name[, default]) : Доступ к атрибуту объекта.
- hasattr(obj,name) : Проверяет, существует ли атрибут.
- setattr(obj,name,value) : Установить атрибут. Если атрибут не существует, создаётся новый атрибут.
- delattr(obj, name) : Удалить атрибут.
Встроенные атрибуты класса Python
- __dict__ : Атрибуты класса (содержит словарь, состоящий из атрибутов данных класса)
- __doc__ : Строка документации класса
- __name__: Имя класса
- __module__: Модуль, в котором определён класс (полное имя класса — '__main__.className'; если класс находится в импортированном модуле mymod, то className.__module__ равно mymod)
- __bases__ : Элементы, составляющие все родительские классы этого класса (содержит кортеж, состоящий из всех родительских классов)
Ниже приведён пример обращения к встроенным атрибутам класса Python:
Пример
Результат выполнения приведённого выше кода выглядит следующим образом:
Employee.__doc__: 所有员工的基类
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}
Уничтожение объектов Python (сборка мусора)
Python использует простую технику подсчёта ссылок для отслеживания и освобождения мусора.
Во внутренней реализации Python ведёт учёт количества ссылок на все используемые объекты.Внутренняя переменная отслеживания, называемая счётчиком ссылок.
Когда объект создаётся, создаётся счётчик ссылок. Когда этот объект больше не нужен, то есть когда счётчик ссылок объекта становится равным 0, он собирается сборщиком мусора. Однако сборка происходит не "немедленно"; интерпретатор освобождает область памяти, занятую объектом-мусором, в подходящий момент.
a = 40 # 创建对象 <40> b = a # 增加引用, <40> 的计数 c = [b] # 增加引用. <40> 的计数 del a # 减少引用 <40> 的计数 b = 100 # 减少引用 <40> 的计数 c[0] = -1 # 减少引用 <40> 的计数
Механизм сборки мусора нацелен не только на объекты со счётчиком ссылок, равным 0, но также может обрабатывать циклические ссылки. Циклические ссылки — это когда два объекта ссылаются друг на друга, но никакие другие переменные на них не ссылаются. В этом случае полагаться только на подсчёт ссылок недостаточно. Сборщик мусора Python на самом деле представляет собой счётчик ссылок и сборщик циклического мусора. В качестве дополнения к подсчёту ссылок сборщик мусора также следит за объектами с большим общим объёмом выделенной памяти (то есть теми, которые не были уничтожены подсчётом ссылок). В таких случаях интерпретатор приостанавливается и пытается очистить все циклы без ссылок.
Пример
Деструктор __del__ вызывается при уничтожении объекта. Когда объект больше не используется, выполняется метод __del__:
Пример
Результат выполнения приведённого выше примера выглядит следующим образом:
3083401324 3083401324 3083401324 Point 销毁
Примечание:Обычно вам нужно определить класс в отдельном файле,
Наследование классов
Одним из главных преимуществ объектно-ориентированного программирования является повторное использование кода, и один из способов достичь этого повторного использования — механизм наследования.
Новый класс, созданный посредством наследования, называетсяподклассомилипроизводным классом, а класс, который наследуется, называетсябазовым классом、родительский классилисуперкласс。
Синтаксис наследования
class 派生类名(基类名)
...
Некоторые особенности наследования в Python:
- 1. Если в подклассе нужен конструктор родительского класса, необходимо явно вызвать конструктор родительского класса или не переопределять конструктор родительского класса. Подробнее см.:объяснение наследования конструктора родительского класса подклассом Python。
- 2. При вызове метода базового класса нужно указать перед ним имя базового класса и включить переменную-параметр self. Разница в том, что при вызове обычных функций внутри класса не нужно включать параметр self.
- 3. Python всегда сначала ищет метод соответствующего типа. Если он не может найти соответствующий метод в производном классе, то затем ищет в базовых классах один за другим. (Сначала он ищет вызываемый метод в текущем классе и переходит к базовому классу только если он не найден.)
Если в кортеже наследования указано более одного класса, это называется "множественное наследование".
Синтаксис:
Объявление производного класса аналогично объявлению его родительского класса. Список наследуемых базовых классов следует после имени класса, как показано ниже:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
Пример
Вывод приведённого выше кода следующий:
调用子类构造方法 调用子类方法 调用父类方法 父类属性 : 200
Вы можете наследовать от нескольких классов
class A: # 定义类 A ..... class B: # 定义类 B ..... class C(A, B): # 继承类 A 和 B .....
Вы можете использовать методы issubclass() или isinstance() для проверки.
- issubclass() - булева функция, определяющая, является ли класс подклассом или потомком другого класса. Синтаксис: issubclass(sub, sup)
- isinstance(obj, Class) Булева функция, возвращающая true, если obj является экземпляром класса Class или экземпляром подкласса Class.
Переопределение методов
Если функциональность метода вашего родительского класса не может удовлетворить ваши потребности, вы можете переопределить метод родительского класса в подклассе:
Пример:
Пример
После выполнения приведённого выше кода вывод будет следующим:
Calling subclass methods
Основные методы перегрузки
В следующей таблице перечислены некоторые общие функции, которые можно переопределить в своих собственных классах:
| Нет. | Метод, Описание и Простой вызов |
|---|---|
| 1 | __init__ ( self [,args...] ) Конструктор Простой вызов метода:obj = className(args) |
| 2 | __del__( self ) Метод-деструктор, удаление объекта Простой вызов метода:del obj |
| 3 | __repr__( self ) Преобразует в форму, читаемую интерпретатором Простой вызов метода:repr(obj) |
| 4 | __str__( self ) Используется для преобразования значения в удобочитаемую форму Простой вызов метода:str(obj) |
| 5 | __cmp__ ( self, x ) Сравнение объектов Простой вызов метода:cmp(obj, x) |
Перегрузка операторов
Python также поддерживает перегрузку операторов, как показано в примере ниже:
Пример
Вывод приведённого выше кода следующий:
Vector(7,8)
Атрибуты и методы класса
Приватные атрибуты класса
__private_attrs: Начинается с двух подчеркиваний, объявляет атрибут приватным, который нельзя использовать или к которому нельзя напрямую обратиться вне класса. При использовании внутри методов класса,self.__private_attrs。
Методы класса
Внутри класса используйтеdefключевое слово, чтобы определить метод для класса. В отличие от обычных определений функций, метод класса должен включать параметр self в качестве первого параметра.
Приватные методы класса
__private_method: Начинается с двух подчеркиваний, объявляет метод приватным и не может быть вызван вне класса. Чтобы вызвать его внутри класса,self.__private_methods
Пример
Python изменяет имя, добавляя в него имя класса:
1
2
2
Traceback (most recent call last):
File "test.py", line 17, in <module>
print counter.__secretCount # 报错,实例不能访问私有变量
AttributeError: JustCounter instance has no attribute '__secretCount'
Python не позволяет экземплярам класса получать доступ к приватным данным, но вы можете использоватьobject._className__attrName( object_name._class_name__private_attribute_name) для доступа к атрибуту. См. следующий пример:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
class Example:
__site = "www.example.com"
example = Example()
print example._Example__site
Выполните приведённый выше код, и результат будет следующим:
www.example.com
Объяснение одинарного подчёркивания, двойного подчёркивания и двойного подчёркивания в начале и конце:
-
__foo__: Определяет специальные методы, обычно системные имена, такие как__init__()и так далее.
-
_foo: Переменная, начинающаяся с одного подчёркивания, представляет переменную защищённого типа, то есть защищённый тип может быть доступен только самому себе и подклассам, и не может использоваться дляfrom module import *
-
__foo: Двойные подчёркивания обозначают переменную приватного типа, которая может быть доступна только самому классу.