Python был объектно-ориентированным языком с момента его появления. Из-за этого создавать и использовать классы и объекты совершенно просто. Эта глава поможет вам стать экспертом в использовании поддержки объектно-ориентированного программирования в Python.
Если у вас нет опыта работы с объектно-ориентированным (ОО) программированием, вы можете обратиться к вводному курсу по нему или хотя бы к какому-то учебнику, чтобы иметь представление об основных понятиях.
Тем не менее, вот небольшое введение объектно-ориентированного программирования (ООП), которое поможет вам быстро —
Обзор терминологии ООП
-
Класс — определенный пользователем прототип для объекта, который определяет набор атрибутов, которые характеризуют любой объект класса. Атрибутами являются члены данных (переменные класса и переменные экземпляра) и методы, доступ к которым осуществляется через точечную запись.
-
Переменная класса — переменная, которая используется всеми экземплярами класса. Переменные класса определены внутри класса, но вне любого из методов класса. Переменные класса используются не так часто, как переменные экземпляра.
-
Член данных — переменная класса или переменная экземпляра, которая содержит данные, связанные с классом и его объектами.
-
Перегрузка функций — назначение более чем одного поведения определенной функции. Выполняемая операция варьируется в зависимости от типов объектов или аргументов.
-
Переменная экземпляра — переменная, которая определена внутри метода и принадлежит только текущему экземпляру класса.
-
Наследование — передача характеристик класса другим классам, которые являются его производными.
-
Экземпляр — индивидуальный объект определенного класса. Например, объект obj, принадлежащий классу Circle, является экземпляром класса Circle.
-
Instantiation — создание экземпляра класса.
-
Метод — особый вид функции, который определен в определении класса.
-
Объект — уникальный экземпляр структуры данных, который определяется его классом. Объект включает в себя как члены данных (переменные класса и переменные экземпляра), так и методы.
-
Перегрузка оператора — назначение более чем одной функции определенному оператору.
Класс — определенный пользователем прототип для объекта, который определяет набор атрибутов, которые характеризуют любой объект класса. Атрибутами являются члены данных (переменные класса и переменные экземпляра) и методы, доступ к которым осуществляется через точечную запись.
Переменная класса — переменная, которая используется всеми экземплярами класса. Переменные класса определены внутри класса, но вне любого из методов класса. Переменные класса используются не так часто, как переменные экземпляра.
Член данных — переменная класса или переменная экземпляра, которая содержит данные, связанные с классом и его объектами.
Перегрузка функций — назначение более чем одного поведения определенной функции. Выполняемая операция варьируется в зависимости от типов объектов или аргументов.
Переменная экземпляра — переменная, которая определена внутри метода и принадлежит только текущему экземпляру класса.
Наследование — передача характеристик класса другим классам, которые являются его производными.
Экземпляр — индивидуальный объект определенного класса. Например, объект obj, принадлежащий классу Circle, является экземпляром класса Circle.
Instantiation — создание экземпляра класса.
Метод — особый вид функции, который определен в определении класса.
Объект — уникальный экземпляр структуры данных, который определяется его классом. Объект включает в себя как члены данных (переменные класса и переменные экземпляра), так и методы.
Перегрузка оператора — назначение более чем одной функции определенному оператору.
Создание классов
Оператор класса создает новое определение класса. Имя класса следует сразу за ключевым словом class, за которым следует двоеточие:
class ClassName: 'Optional class documentation string' class_suite
-
Класс имеет строку документации, к которой можно получить доступ через ClassName .__ doc__ .
-
Class_suite состоит из всех операторов компонентов, определяющих членов класса, атрибуты данных и функции.
Класс имеет строку документации, к которой можно получить доступ через ClassName .__ doc__ .
Class_suite состоит из всех операторов компонентов, определяющих членов класса, атрибуты данных и функции.
пример
Ниже приведен пример простого класса Python —
class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
-
Переменная empCount является переменной класса, значение которой является общим для всех экземпляров этого класса. Доступ к нему можно получить как Employee.empCount внутри класса или за его пределами.
-
Первый метод __init __ () — это специальный метод, который называется конструктором класса или методом инициализации, который Python вызывает при создании нового экземпляра этого класса.
-
Вы объявляете другие методы класса, как обычные функции, за исключением того, что первый аргумент каждого метода — это self . Python добавляет аргумент self в список для вас; вам не нужно включать его при вызове методов.
Переменная empCount является переменной класса, значение которой является общим для всех экземпляров этого класса. Доступ к нему можно получить как Employee.empCount внутри класса или за его пределами.
Первый метод __init __ () — это специальный метод, который называется конструктором класса или методом инициализации, который Python вызывает при создании нового экземпляра этого класса.
Вы объявляете другие методы класса, как обычные функции, за исключением того, что первый аргумент каждого метода — это self . Python добавляет аргумент self в список для вас; вам не нужно включать его при вызове методов.
Создание объектов экземпляра
Чтобы создать экземпляры класса, вы вызываете класс, используя имя класса, и передаете любые аргументы, которые принимает его метод __init__ .
"This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000)
Доступ к атрибутам
Вы получаете доступ к атрибутам объекта, используя оператор точки с объектом. Переменная класса будет доступна с использованием имени класса следующим образом:
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
Теперь, объединяя все концепции —
#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary "This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" 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 # Add an 'age' attribute. emp1.age = 8 # Modify 'age' attribute. del emp1.age # Delete 'age' attribute.
Вместо использования обычных операторов для доступа к атрибутам, вы можете использовать следующие функции:
-
Getattr (obj, name [, default]) — для доступа к атрибуту объекта.
-
Hasattr (obj, name) — проверить, существует атрибут или нет.
-
Setattr (obj, name, value) — установить атрибут. Если атрибут не существует, он будет создан.
-
Delattr (obj, name) — удалить атрибут.
Getattr (obj, name [, default]) — для доступа к атрибуту объекта.
Hasattr (obj, name) — проверить, существует атрибут или нет.
Setattr (obj, name, value) — установить атрибут. Если атрибут не существует, он будет создан.
Delattr (obj, name) — удалить атрибут.
hasattr(emp1, 'age') # Returns true if 'age' attribute exists getattr(emp1, 'age') # Returns value of 'age' attribute setattr(emp1, 'age', 8) # Set attribute 'age' at 8 delattr(empl, 'age') # Delete attribute 'age'
Встроенные атрибуты класса
Каждый класс Python поддерживает следующие встроенные атрибуты, и к ним можно получить доступ, используя оператор точки, как и любой другой атрибут —
-
__dict__ — словарь, содержащий пространство имен класса.
-
__doc__ — Строка документации класса или нет, если она не определена.
-
__name__ — Имя класса.
-
__module__ — Имя модуля, в котором определяется класс. Этот атрибут «__main__» в интерактивном режиме.
-
__bases__ — возможно пустой кортеж, содержащий базовые классы, в порядке их появления в списке базовых классов.
__dict__ — словарь, содержащий пространство имен класса.
__doc__ — Строка документации класса или нет, если она не определена.
__name__ — Имя класса.
__module__ — Имя модуля, в котором определяется класс. Этот атрибут «__main__» в интерактивном режиме.
__bases__ — возможно пустой кортеж, содержащий базовые классы, в порядке их появления в списке базовых классов.
Для приведенного выше класса давайте попробуем получить доступ ко всем этим атрибутам —
#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary print "Employee.__doc__:", Employee.__doc__ print "Employee.__name__:", Employee.__name__ print "Employee.__module__:", Employee.__module__ print "Employee.__bases__:", Employee.__bases__ print "Employee.__dict__:", Employee.__dict__
Когда приведенный выше код выполняется, он дает следующий результат —
Employee.__doc__: Common base class for all employees Employee.__name__: Employee Employee.__module__: __main__ Employee.__bases__: () Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}
Уничтожение объектов (Сборка мусора)
Python автоматически удаляет ненужные объекты (встроенные типы или экземпляры классов), чтобы освободить пространство памяти. Процесс, посредством которого Python периодически восстанавливает блоки памяти, которые больше не используются, называется сборкой мусора.
Сборщик мусора в Python запускается во время выполнения программы и запускается, когда счетчик ссылок на объект достигает нуля. Количество ссылок объекта изменяется по мере изменения количества псевдонимов, которые на него указывают.
Счетчик ссылок на объект увеличивается, когда ему присваивается новое имя или он помещается в контейнер (список, кортеж или словарь). Счетчик ссылок объекта уменьшается, когда он удаляется с помощью del , его ссылка переназначается или его ссылка выходит за пределы области видимости. Когда счетчик ссылок объекта достигает нуля, Python собирает его автоматически.
a = 40 # Create object <40> b = a # Increase ref. count of <40> c = [b] # Increase ref. count of <40> del a # Decrease ref. count of <40> b = 100 # Decrease ref. count of <40> c[0] = -1 # Decrease ref. count of <40>
Обычно вы не замечаете, когда сборщик мусора уничтожает потерянный экземпляр и освобождает его пространство. Но класс может реализовать специальный метод __del __ () , называемый деструктором, который вызывается, когда экземпляр собирается быть уничтоженным. Этот метод может использоваться для очистки любых ресурсов памяти, используемых экземпляром.
пример
Этот деструктор __del __ () печатает имя класса экземпляра, который должен быть уничтожен —
#!/usr/bin/python class Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed" pt1 = Point() pt2 = pt1 pt3 = pt1 print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts del pt1 del pt2 del pt3
Когда приведенный выше код выполняется, он дает следующий результат —
3083401324 3083401324 3083401324 Point destroyed
Примечание. В идеале вы должны определять свои классы в отдельном файле, а затем импортировать их в основной файл программы с помощью оператора import .
Наследование классов
Вместо того, чтобы начинать с нуля, вы можете создать класс, выведя его из ранее существовавшего класса, перечислив родительский класс в скобках после имени нового класса.
Дочерний класс наследует атрибуты своего родительского класса, и вы можете использовать эти атрибуты, как если бы они были определены в дочернем классе. Дочерний класс также может переопределять элементы данных и методы родительского класса.
Синтаксис
Производные классы объявляются так же, как их родительский класс; однако список базовых классов для наследования дается после имени класса —
class SubClassName (ParentClass1[, ParentClass2, ...]): 'Optional class documentation string' class_suite
пример
#!/usr/bin/python class Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttr class Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method' c = Child() # instance of child c.childMethod() # child calls its method c.parentMethod() # calls parent's method c.setAttr(200) # again call parent's method c.getAttr() # again call parent's method
Когда приведенный выше код выполняется, он дает следующий результат —
Calling child constructor Calling child method Calling parent method Parent attribute : 200
Аналогичным образом вы можете управлять классом из нескольких родительских классов следующим образом:
class A: # define your class A ..... class B: # define your class B ..... class C(A, B): # subclass of A and B .....
Вы можете использовать функции issubclass () или isinstance (), чтобы проверить отношения двух классов и экземпляров.
-
Булева функция issubclass (sub, sup) возвращает true, если данный подкласс sub действительно является подклассом суперкласса sup .
-
Булева функция isinstance (obj, Class) возвращает true, если obj является экземпляром класса Class или экземпляром подкласса Class
Булева функция issubclass (sub, sup) возвращает true, если данный подкласс sub действительно является подклассом суперкласса sup .
Булева функция isinstance (obj, Class) возвращает true, если obj является экземпляром класса Class или экземпляром подкласса Class
Переопределяющие методы
Вы всегда можете переопределить ваши родительские методы класса. Одна из причин переопределения родительских методов заключается в том, что вам может потребоваться особая или другая функциональность в вашем подклассе.
пример
#!/usr/bin/python class Parent: # define parent class def myMethod(self): print 'Calling parent method' class Child(Parent): # define child class def myMethod(self): print 'Calling child method' c = Child() # instance of child c.myMethod() # child calls overridden method
Когда приведенный выше код выполняется, он дает следующий результат —
Calling child method
Базовые методы перегрузки
В следующей таблице перечислены некоторые общие функции, которые вы можете переопределить в своих собственных классах.
Sr.No. | Метод, описание и пример вызова |
---|---|
1 |
__init__ (self [, args …]) Конструктор (с любыми необязательными аргументами) Пример вызова: obj = className (args) |
2 |
__del __ (самостоятельно) Деструктор, удаляет объект Образец звонка: del obj |
3 |
__repr __ (самостоятельно) Оцениваемое строковое представление Пример вызова: repr (obj) |
4 |
__str __ (самостоятельно) Печатное представление строки Пример вызова: str (obj) |
5 |
__cmp__ (self, x) Сравнение объектов Пример вызова: cmp (obj, x) |
__init__ (self [, args …])
Конструктор (с любыми необязательными аргументами)
Пример вызова: obj = className (args)
__del __ (самостоятельно)
Деструктор, удаляет объект
Образец звонка: del obj
__repr __ (самостоятельно)
Оцениваемое строковое представление
Пример вызова: repr (obj)
__str __ (самостоятельно)
Печатное представление строки
Пример вызова: str (obj)
__cmp__ (self, x)
Сравнение объектов
Пример вызова: cmp (obj, x)
Операторы перегрузки
Предположим, что вы создали класс Vector для представления двумерных векторов. Что произойдет, когда вы добавите оператор «плюс»? Скорее всего, Python будет кричать на вас.
Однако вы можете определить метод __add__ в вашем классе для выполнения сложения векторов, и тогда оператор плюс будет вести себя так, как ожидалось:
пример
#!/usr/bin/python class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print v1 + v2
Когда приведенный выше код выполняется, он дает следующий результат —
Vector(7,8)
Скрытие данных
Атрибуты объекта могут или не могут быть видны вне определения класса. Вам необходимо присвоить имена атрибутам с двойным префиксом подчеркивания, и тогда эти атрибуты не будут напрямую видны посторонним.
пример
#!/usr/bin/python class JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.__secretCount
Когда приведенный выше код выполняется, он дает следующий результат —
1 2 Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCount AttributeError: JustCounter instance has no attribute '__secretCount'
Python защищает этих членов, внутренне изменяя имя, чтобы включить имя класса. Вы можете получить доступ к таким атрибутам как object._className__attrName . Если вы заменили свою последнюю строку следующим образом, то она работает для вас —
......................... print counter._JustCounter__secretCount
Когда приведенный выше код выполняется, он дает следующий результат —