Коль ты о людях говоришь плохое, Пускай ты прав — нутро в тебе дурное (Саади).

Python 3 – Объектно-ориентированный язык

FavoriteLoadingДобавить в избранное
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...
9 ноября 2017
Python 3 - объектно-ориентированный язык
Python является объектно-ориентированным языком с того времени, как он начал существовать. В связи с этим, создание и использование классов и объектов прямо-таки легко. Эта глава поможет вам стать экспертом в использовании объектно-ориентированного программирования в Python.

Если у вас нет какого-либо предыдущего опыта работы с объектно-ориентированным (ОО) программированием, вы можете пройти вводный курс по нему или, по крайней мере, прочитать учебник, чтобы у вас было понимание основных концепций.

Однако, здесь есть небольшое введение в объектно-ориентированное программирование (ООП), чтобы помочь вам:

Обзор терминологии ООП

  • Класс – определенный пользователем прототип для объекта, который определяет набор атрибутов, которые характеризуют любой объект класса. Атрибуты являются членами данных (переменные класса и переменные экземпляра) и методы, доступ к которым  с помощью запись через точку.
  • Переменная класса – переменная, которая разделяется всеми экземплярами класса. Переменные класса определяются в пределах класса, но не в любом методе класса. Переменные класса не используются так часто, как переменные экземпляра.
  • Элемент данных – класс переменной или экземпляра переменной, которая содержит данные, связанные с классом и его объектами.
  • Перегрузка функций – присвоение более одного поведения определенной функции. Выполняемая операция зависит от типов задействованных объектов или аргументов.
  • Переменная экземпляра – переменная, определенная внутри метода и относится только к текущему экземпляру класса.
  • Наследование – передача характеристик одного класса к другим классам, которые являются производными от него.
  • Экземпляр – индивидуальный объект определенного класса. Объект OBJ, который принадлежит к классу Circle, например, является экземпляром класса Circle.
  • Instantiation – создание экземпляра класса.
  • Метод – особый вид функции, который определяется в определении класса.
  • Объект – уникальный экземпляр структуры данных, который определяется его классом. Объект включает в себя как элементы данных (переменные класса и переменные экземпляра) и методы.
  • Перегрузка операторов – Назначение более одной функции к конкретному оператору.

Создание классов

Оператор class создает новое определение класса. Имя класса следует сразу за ключевым словом class с последующим двоеточием, следующим образом:

class ClassName:
   'Optional class documentation string'
   class_suite

 

  • Класс имеет строку документации, доступ к которой осуществляется через ClassName .__ doc__.
  • Class_suite состоит из всех компонентов утверждений, определяющих члена класса, атрибуты данных и функцию.

Пример

Ниже приведен пример простого класса в Python:

class Employee:
   'Общий базовый класс для всех сотрудников'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Всего сотрудников %d" % Employee.empCount

   def displayEmployee(self):
      print "Имя : ", self.name,  ", Зарплата: ", self.salary

 

  • Переменная empCount является переменной класса, чье значение является общим для всех экземпляров этого класса. Она может быть доступна как Employee.empCount внутри класса или вне класса.
  • Первый метод __init __ () это специальный метод, который вызывается конструктор класса или метод инициализации, Python требует при создании нового экземпляра этого класса.
  • Вы объявляете другие методы класса, как обычные функции, за исключением того, что первый аргумент каждого метода является самостоятельным . Python добавляет аргумент self в список для вас; Вам не нужно включать его при вызове методов.

Создание экземпляров объектов

Для создания экземпляров класса, вызывается класс, используя имя класса и передать в аргументах метод  __init__.

Это создаст первый объект класса сотрудника
emp1 = Employee("AndreyEx", 80000)
Это позволит создать второй объект класса employee
emp2 = Employee("Alex", 65000)

 

Доступ к атрибутам

Вы можете получить доступ к атрибутам объекта, используя оператор точка с объектом. Переменная класса получит доступ, используя имя класса следующим образом:

emp1.displayEmployee()
emp2.displayEmployee()
print ("Всего сотрудников %d" % Employee.empCount)

 

Теперь, сложив все понятия вместе:

#!/usr/bin/python3

class Employee:
   'Общий базовый класс для всех сотрудников'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print ("Всего сотрудников %d" % Employee.empCount)

   def displayEmployee(self):
      print ("Имя : ", self.name,  ", Зарплата: ", self.salary)


#Это создаст первый объект класса сотрудника"
emp1 = Employee("AndreyEx", 80000)
#Это позволит создать второй объект класса employee"
emp2 = Employee("Alex", 65000)
emp1.displayEmployee()
emp2.displayEmployee()
print ("Всего сотрудников %d" % Employee.empCount)

 

Когда этот код выполниться, он выведет следующий результат:

Имя :  AndreyEx,Зарплата:  80000
Имя :  Alex,Зарплата:  65000
Всего сотрудников 2

 

Вы можете добавлять, удалять или изменять атрибуты классов и объектов в любое время:

emp1.salary = 7000  # Add an 'salary' attribute.
emp1.name = 'xyz'  # Modify 'age' attribute.
del emp1.salary  # Delete 'age' attribute.

 

Вместо того, чтобы использовать обычные заявления атрибутов доступа, вы можете использовать следующие функции:

  • GetAttr (объект, имя [, по умолчанию]) – для доступа к атрибуту объекта.
  • Hasattr (объект, имя) – проверить, существует атрибут или нет.
  • SetAttr (объект, имя, значение) – установить атрибут. Если атрибут не существует, то он будет создан.
  • Delattr (объект, имя) – для удаления атрибута.
hasattr(emp1, 'salary')    # Возвращает true, если атрибут 'salary' существует
getattr(emp1, 'salary')    # Возвращает значение атрибута 'salary'
setattr(emp1, 'salary', 7000) # Устанавливает атрибут 'salary' в 70000
delattr(emp1, 'salary')    # Удаляет атрибут 'salary'

 

Встроенные атрибуты класса

Каждый класс Python поддерживает следующие встроенные атрибуты и их можно получить с помощью оператора точки, как и любой другой атрибут:

  • __dict__ – Словарь, содержащий пространство имен класса.
  • __doc__ – Документация класса string или нет, если не определено.
  • __name__ – Имя класса.
  • __module__ – Имя модуля, в котором определен класс. Это атрибут «__main__» в интерактивном режиме.
  • __bases__ – Возможно пустой кортеж, содержащий базовые классы, в порядке их появления в списке базового класса.

Для приведенного выше класса давайте попробуем открыть все эти атрибуты:

#!/usr/bin/python3

class Employee:
   'Общий базовый класс для всех сотрудников'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print ("Всего сотрудников %d" % Employee.empCount)

   def displayEmployee(self):
      print ("Имя : ", self.name,  ", Зарплата: ", self.salary)

emp1 = Employee("AndreyEx", 80000)
emp2 = Employee("Alex", 65000)
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__: Общий базовый класс для всех сотрудников
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {
   'displayCount': <function Employee.displayCount at 0x0160D2B8>, 
   '__module__': '__main__', '__doc__': 'Общий базовый класс для всех сотрудников', 
   'empCount': 2, '__init__': 
   <function Employee.__init__ at 0x0124F810>, 'displayEmployee': 
   <function Employee.displayEmployee at 0x0160D300>,
   '__weakref__': 
   <attribute '__weakref__' of 'Employee' objects>, '__dict__': 
   <attribute '__dict__' of 'Employee' objects>
}

Уничтожение объектов (Garbage Collection)

Python удаляет ненужные объекты (встроенные типы или экземпляры классов) автоматически, чтобы освободить место в памяти. Процесс, посредством которого Python периодически восстанавливает блоки памяти, которые больше не находятся в использовании называется как сборщики мусора.

Сборщик мусора в Python работают во время выполнения программы и срабатывают, когда счетчик ссылок объекта достигает нуля. Счетчик ссылок объекта изменяется, как число псевдонимов, которые указывают на ее изменения.

Счетчик ссылок объекта увеличивается, когда ему присваивается новое имя или помещается в контейнер (список, кортеж, или словарь). Счетчик ссылок объекта уменьшается, когда он удаляется с del, его ссылка переназначается, или его ссылка выходит из области видимости. Когда счетчик ссылок объекта достигает нуля, Python собирает его автоматически.

a = 40      # Создание объекта <40>
b = a       # Увеличение счетчика ссылок <40> 
c = [b]     # Увеличение счетчика ссылок <40> 

del a       # Уменьшение счетчика ссылок <40>
b = 100     # Уменьшение счетчика ссылок <40> 
c[0] = -1   # Уменьшение счетчика ссылок <40>

 

Как правило, вы не замечаете, когда сборщик мусора уничтожает обнулившийся экземпляр и высвобождает его пространство. Тем не менее, класс может реализовать специальный метод  __del __(), называется деструктор, который вызывается, когда экземпляр собирается быть уничтоженным. Этот метод может быть использован для очистки любых ресурсов из памяти, используемых экземпляр.

Пример

Деструктор __del __ () печатает имя класса экземпляра, который собирается быть уничтожен:

#!/usr/bin/python3

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));   # печатает идентификаторы obejcts
del pt1
del pt2
del pt3

 

Когда этот код выполниться, он выведет следующий результат:

3083401324 3083401324 3083401324
Point destroyed

 

Примечание:
В идеале, если вы хотите определить свои классы в отдельном файле, то вы должны импортировать их в основной файл программы с помощью заявления import.

В приведенном выше примере, предполагая определение класса точки, содержащейся в point.py и нет никакого другого исполняемого кода в нем.

#!/usr/bin/python3
import point
p1 = point.Point()

 

Наследование классов

Вместо того чтобы начать с нуля, вы можете создать класс, выводя его из предварительно существующего класса, перечислив родительский класс в скобках после нового имени класса.

Дочерний класс наследует атрибуты своего родительского класса, и вы можете использовать эти атрибуты, как если бы они были определены в дочернем классе. Дочерний класс может также переопределить элементы данных и методы от родителей.

Синтаксис

Производные классы объявляются так же, как их родительский класс; Однако, список базовых классов наследуются после имени класса:

class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Необязательная строка документации класса'
   class_suite

 

Пример

#!/usr/bin/python3

class Parent:        # определить родительский класс
   parentAttr = 100
   def __init__(self):
      print ("Вызов родительского конструктора")

   def parentMethod(self):
      print ('Вызов родительского метода')

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print ("Родительский атрибут :", Parent.parentAttr)

class Child(Parent): # определить дочерний класс
   def __init__(self):
      print ("Вызов дочернего конструктора")

   def childMethod(self):
      print ('Вызов дочернего метода')

c = Child()          # дочерний экземпляр
c.childMethod()      # дочерний экземпляр называет свой метод
c.parentMethod()     # вызывает родительский метод
c.setAttr(200)       # снова вызов родительского метода
c.getAttr()          # снова вызов родительского метода

 

Когда этот код выполнится, он выведет следующий результат:

Вызов дочернего конструктора
Вызов дочернего метода
Вызов родительского метода
Родительский атрибут : 200

 

Аналогичным образом, вы можете управлять классом от нескольких родительских классов следующим образом:

class A:        # определите свой класс A
.....

class B:         # определите свой класс B
.....

class C(A, B):   # Субкласс A и B
.....

 

Вы можете использовать функции issubclass() или isinstance() для проверки отношения двух классов и экземпляров.

  • Функция issubclass(sub, sup) возвращает логическое значение true, если данный подкласс sub действительно подкласс суперкласса sup.
  • Функция isinstance(obj, Class) возвращает логическое true, если obj является экземпляром класса Class или является экземпляром подкласса Class.

Переопределение методов

Вы всегда можете переопределить методы родительского класса. Одной из причин переопределения методов родителя является то, что вы можете использовать специальную или иную функцию в подклассе.

Пример

#!/usr/bin/python3

class Parent:        # определить родительский класс
   def myMethod(self):
      print ('Вызов родительского метода')

class Child(Parent): # определить дочерний класс
   def myMethod(self):
      print ('Вызов дочернего метода')

c = Child()          # дочерний экземпляр
c.myMethod()         # дочерний класс вызывает переопределенный метод

 

Когда этот код выполнится, он выведет следующий результат:

Вызов дочернего метода

Методы базовой перегрузки

В следующей таблице перечислены некоторые общие функциональные возможности, которые вы можете переопределить в своих классах:

Метод, описание и пример вызова
1__init__ ( self [,args…] )

Конструктор (с любыми дополнительными аргументами)

Пример вызова: obj = className(args)

2__del__( self )

Деструктор, удаляет объект

Пример вызова: del obj

3__repr__( self )

Evaluatable строковое представление

Пример вызова: repr(obj)

4__str__( self )

Версия для печати строкового представления

Пример вызова: str(obj)

5__cmp__ ( self, x )

Сравнение объектов

Пример вызова: cmp(obj, x)

Перегрузка операций

Предположим, что вы создали класс Vector для представления двухмерных векторов. Что происходит, когда вы используете оператор плюс, чтобы добавить их? Скорее всего, Python будет ругаться на вас.

Можно, однако, определить метод  __add__ в классе для выполнения векторного сложения, а затем оператор плюс будет вести себя в соответствии с ожиданиями:

Пример

#!/usr/bin/python3

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/python3

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 защищает эти члены путем внутреннего изменения имени, чтобы включить имя класса. Вы можете получить доступ к таким атрибутам, как объект ._className__attrName. Если вы заменили бы последнюю строку следующим образом, то она заработает

.........................
print (counter._JustCounter__secretCount)

 

Когда этот код выполниться, вывод будет следующий:

1
2
2

Python 3 - объектно-ориентированный язык

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Просмотров: 145

Если статья понравилась, то поделитесь ей в социальных сетях:

Читайте также

    Добавить комментарий

    Войти с помощью: 

    Ваш e-mail не будет опубликован. Обязательные поля помечены *

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам:

    Заполните форму и наш менеджер перезвонит Вам в самое ближайшее время!

    badge
    Обратный звонок 1
    Отправить
    galka

    Спасибо! Ваша заявка принята

    close
    galka

    Спасибо! Ваша заявка принята

    close