ООП — PythonRu https://pythonru.com Изучайте Python на русском: учебные руководства Python для разработчиков с разным уровнем знаний, рекомендации книг и курсов Python, новости, примеры кода, статьи и уроки Thu, 04 Mar 2021 08:25:34 +0000 ru-RU hourly 1 https://pythonru.com/wp-content/uploads/2018/11/cropped-pythonru-icon-32x32.png ООП — PythonRu https://pythonru.com 32 32 Класс и объект в Python https://pythonru.com/osnovy/klass-i-obekt-v-python Sat, 19 Oct 2019 13:43:58 +0000 https://pythonru.com/?p=1692

Объектно-ориентированное программирование в Python

Python — это процедурно-ориентированный и одновременно объектно-ориентированный язык программирования.

Процедурно-ориентированный

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

Объектно-ориентированный

«Объектно-ориентированный» подразумевает наличие классов. Есть возможность создавать классы, представляющие собой прототипы для будущих объектов.

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

Синтаксис для написания нового класса:

class ClassName:
    'Краткое описание класса (необязательно)'
    # Код ...
  • Для создания класса пишется ключевое слово class, его имя и двоеточие (:). Первая строчка в теле класса описывает его. (По желанию) получить доступ к этой строке можно с помощью ClassName.__doc__
  • В теле класса допускается объявление атрибутов, методов и конструктора.

Атрибут:

Атрибут — это элемент класса. Например, у прямоугольника таких 2: ширина (width) и высота (height).

Метод:

  • Метод класса напоминает классическую функцию, но на самом деле — это функция класса. Для использования ее необходимо вызывать через объект.
  • Первый параметр метода всегда self (ключевое слово, которое ссылается на сам класс).

Конструктор:

  • Конструктор — уникальный метод класса, который называется __init__.
  • Первый параметр конструктора во всех случаях self (ключевое слово, которое ссылается на сам класс).
  • Конструктор нужен для создания объекта.
  • Конструктор передает значения аргументов свойствам создаваемого объекта.
  • В одном классе всегда только один конструктор.
  • Если класс определяется не конструктором, Python предположит, что он наследует конструктор родительского класса.
# Прямоугольник.
class Rectangle :
    'Это класс Rectangle'
    # Способ создания объекта (конструктор)
    def __init__(self, width, height):         
        self.width= width
        self.height = height

    def getWidth(self):        
        return self.width
     
    def getHeight(self):        
        return self.height
 
    # Метод расчета площади.
    def getArea(self):
        return self.width * self.height

Создание объекта с помощью класса Rectangle:

Создание объекта с помощью класса Rectangle

# Создаем 2 объекта: r1 & r2
r1 = Rectangle(10,5)
r2 = Rectangle(20,11)
 
print("r1.width = ", r1.width)
print("r1.height = ", r1.height)
print("r1.getWidth() = ", r1.getWidth())
print("r1.getArea() = ", r1.getArea())
 
print("-----------------")
 
print("r2.width = ", r2.width)
print("r2.height = ", r2.height)
print("r2.getWidth() = ", r2.getWidth())
print("r2.getArea() = ", r2.getArea())

Расчет площади класса Rectangle

Что происходит при создании объекта с помощью класса?

При создании объекта класса Rectangle запускается конструктор выбранного класса, и атрибутам нового объекта передаются значения аргументов. Как на этом изображении:

Конструктор выбранного класса

Конструктор с аргументами по умолчанию

В других языках программирования конструкторов может быть несколько. В Python — только один. Но этот язык разрешает задавать значение по умолчанию.

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

class Person:
    # Параметры возраста и пола имеют значение по умолчанию.
    def __init__(self, name, age=1, gender="Male"):
        self.name = name
        self.age = age 
        self.gender= gender
         
    def showInfo(self):
        print("Name: ", self.name)
        print("Age: ", self.age)
        print("Gender: ", self.gender)

Например:

from person import Person
 
# Создать объект Person.
aimee = Person("Aimee", 21, "Female")
aimee.showInfo()
print(" --------------- ")
 
# возраст по умолчанию, пол.
alice = Person( "Alice" )
alice.showInfo()
 
print(" --------------- ")
 
# Пол по умолчанию.
tran = Person("Tran", 37)
tran.showInfo()

Конструктор с аргументами по умолчанию

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

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

Если объект AA — это просто ссылка на объект BB, то он не будет сущностью, занимающей отдельную ячейку памяти. Вместо этого он лишь ссылается на местоположение BB.

Как происходит сравнение объектов

Оператор == нужен, чтобы узнать, ссылаются ли два объекта на одно и то же место в памяти. Он вернет True, если это так. Оператор != вернет True, если сравнить 2 объекта, которые ссылаются на разные места в памяти.

from rectangle import Rectangle


r1 = Rectangle(20, 10)
r2 = Rectangle(20 , 10)
r3 = r1
 
# Сравните r1 и r2
test1 = r1 == r2 # --> False
# Сравните r1 и r3
test2 = r1 == r3 # --> True
 
print ("r1 == r2 ? ", test1) 
print ("r1 == r3 ? ", test2)

print (" -------------- ")
 
print ("r1 != r2 ? ", r1 != r2)
print ("r1 != r3 ? ", r1 != r3)

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

Атрибуты

В Python есть два похожих понятия, которые на самом деле отличаются:

  1. Атрибуты
  2. Переменные класса

Стоит разобрать на практике:

class Player:
    # Переменная класса
    minAge  = 18
    maxAge = 50
     
    def __init__(self, name, age):
        self.name = name
        self.age = age

Атрибут

Объекты, созданные одним и тем же классом, будут занимать разные места в памяти, а их атрибуты с «одинаковыми именами» — ссылаться на разные адреса. Например:

Объекты одного класса занимают разные места в памяти

from player import Player 
 
 
player1 = Player("Tom", 20)
 
player2 = Player("Jerry", 20)
 
print("player1.name = ", player1.name)
print("player1.age = ", player1.age)
 
print("player2.name = ", player2.name)
print("player2.age = ", player2.age)
 
print(" ------------ ")
 
print("Assign new value to player1.age = 21 ")
 
# Присвойте новое значение атрибуту возраста player1.
player1.age = 21
 
print("player1.name = ", player1.name)
print("player1.age = ", player1.age)
 
print("player2.name = ", player2.name)
print("player2.age = ", player2.age)

Изменение значений атрибутов

Python умеет создавать новые атрибуты для уже существующих объектов. Например, объект player1 и новый атрибут address.

from player import Player 
 
 
player1 = Player("Tom", 20)
player2 = Player("Jerry", 20)
 
# Создайте новый атрибут с именем «address» для player1.
player1.address = "USA"
 
print("player1.name = ", player1.name)
print("player1.age = ", player1.age)
print("player1.address = ", player1.address)
 
print(" ------------------- ")
 
print("player2.name = ", player2.name)
print("player2.age = ", player2.age)
 
# player2 е имеет атрибута 'address' (Error!!)
print("player2.address = ", player2.address)

Вывод:

player1.name =  Tom
player1.age =  20
player1.address =  USA
 ------------------- 
player2.name =  Jerry
player2.age =  20
Traceback (most recent call last):
  File "C:/Users/gvido/class.py", line 27, in <module>
    print("player2.address = ", player2.address)
AttributeError: 'Player' object has no attribute 'address'

Атрибуты функции

Обычно получать доступ к атрибутам объекта можно с помощью оператора «точка» (например, player1.name). Но Python умеет делать это и с помощью функции.

Функция Описание
getattr (obj, name[,default]) Возвращает значение атрибута или значение по умолчанию, если первое не было указано
hasattr (obj, name) Проверяет атрибут объекта — был ли он передан аргументом «name»
setattr (obj, name, value) Задает значение атрибута. Если атрибута не существует, создает его
delattr (obj, name) Удаляет атрибут
from player import Player 
 
 
player1 = Player("Tom", 20)
 
# getattr(obj, name[, default])
print("getattr(player1,'name') = " , getattr(player1,"name"))

print("setattr(player1,'age', 21): ")
# setattr(obj,name,value) 
setattr(player1,"age", 21)
print("player1.age = ", player1.age)
 
# Проверка, что player1 имеет атрибут 'address'?
hasAddress =  hasattr(player1, "address")
print("hasattr(player1, 'address') ? ", hasAddress)
 
# Создать атрибут 'address' для объекта 'player1'
print("Create attribute 'address' for object 'player1'")
setattr(player1, 'address', "USA")
print("player1.address = ", player1.address)
 
# Удалить атрибут 'address'.
delattr(player1, "address")

Вывод:

getattr(player1,'name') =  Tom
setattr(player1,'age', 21): 
player1.age =  21
hasattr(player1, 'address') ?  False
Create attribute 'address' for object 'player1'
player1.address =  USA

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

Объекты класса — дочерние элементы по отношению к атрибутам самого языка Python. Таким образом они заимствуют некоторые атрибуты:

Атрибут Описание
__dict__ Предоставляет данные о классе коротко и доступно, в виде словаря
__doc__ Возвращает строку с описанием класса, или None, если значение не определено
__class__ Возвращает объект, содержащий информацию о классе с массой полезных атрибутов, включая атрибут __name__
__module__ Возвращает имя «модуля» класса или __main__, если класс определен в выполняемом модуле.
class Customer:
    'Это класс Customer'
    def __init__(self, name, phone, address):        
        self.name = name
        self.phone = phone
        self.address = address
 
  
john = Customer("John",1234567, "USA")
 
print ("john.__dict__ = ", john.__dict__)
print ("john.__doc__ = ", john.__doc__)
print ("john.__class__ = ", john.__class__)
print ("john.__class__.__name__ = ", john.__class__.__name__) 
print ("john.__module__ = ", john.__module__)  

Вывод:

john.__dict__ =  {'name': 'John', 'phone': 1234567, 'address': 'USA'}
john.__doc__ =  Это класс Customer
john.__class__ =  <class '__main__.Customer'>
john.__class__.__name__ =  Customer
john.__module__ =  __main__

Переменные класса

Переменные класса в Python — это то же самое, что Field в других языках, таких как Java или С#. Получить к ним доступ можно только с помощью имени класса или объекта.

Для получения доступа к переменной класса лучше все-таки использовать имя класса, а не объект. Это поможет не путать «переменную класса» и атрибуты.

У каждой переменной класса есть свой адрес в памяти. И он доступен всем объектам класса.
Переменные класса

from player import Player 
 
 
player1 = Player("Tom", 20)
player2 = Player("Jerry", 20)
 
# Доступ через имя класса.
print ("Player.minAge = ", Player.minAge)
 
# Доступ через объект.
print("player1.minAge = ", player1.minAge) 
print("player2.minAge = ", player2.minAge)
 
print(" ------------ ") 

print("Assign new value to minAge via class name, and print..")
 
# Новое значение minAge через имя класса
Player.minAge = 19
 
print("Player.minAge = ", Player.minAge) 
print("player1.minAge = ", player1.minAge) 
print("player2.minAge = ", player2.minAge)

Вывод:

Player.minAge =  18
player1.minAge =  18
player2.minAge =  18
 ------------ 
Assign new value to minAge via class name, and print..
Player.minAge =  19
player1.minAge =  19
player2.minAge =  19

Составляющие класса или объекта

В Python присутствует функция dir, которая выводит список всех методов, атрибутов и переменных класса или объекта.

from player import Player
 
 
# Вывести список атрибутов, методов и переменных объекта 'Player'
print(dir(Player))
print("\n\n")
 
player1 = Player("Tom", 20)
player1.address ="USA"

# Вывести список атрибутов, методов и переменных объекта 'player1'
print(dir(player1))

Вывод:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', 
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', 
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__weakref__', 'maxAge', 'minAge']  

  
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', 
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', 
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', 
'__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__weakref__', 'address', 'age', 'maxAge', 
'minAge', 'name']
]]>
№19 Классы и объекты Python / Уроки по Python для начинающих https://pythonru.com/uroki/klassy-i-obekty-python-uroki-po-python-dlja-nachinajushhih Tue, 25 Dec 2018 17:14:52 +0000 https://pythonru.com/?p=864

Предыдущий урок: Массивы

Python — объектно-ориентированный язык программирования. Почти все в Python — это объект с его свойствами и методами. Класс похож на конструктор объекта или ‘‘проект’’ для создания объектов.

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

Для того, чтобы создать класс, используйте ключевое слово class.
Создадим класс с именем MyClass и свойством x:

class MyClass:
    x = 5

Создание объекта

Теперь мы можем использовать класс под названием myClass для создания объектов.
Создадим объект под названием p1, и выведем значение x:

p1 = MyClass()
print(p1.x)

Вывод:

5

Функция init

Приведенные выше примеры — это классы и объекты в их простейшей форме и не очень полезны в приложениях.
Чтобы понять значение классов, нам нужно понять встроенную функцию __init__.

У всех классов есть функция под названием __init__(), которая всегда выполняется при создании объекта. Используйте функцию __init__() для добавления значений свойствам объекта или других операций, которые необходимо выполнить, при создании объекта.
Для создания класса под названием Person, воспользуемся функцией __init__(), что бы добавить значения для имени и возраста:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


p1 = Person("Василий",  36)    
print(p1.name)  
print(p1.age)

Вывод:

Василий
36

Обратите внимание: Функция __init__() автоматически вызывается каждый раз при использовании класса для создания нового объекта.

Методы объектов

Объекты также содержат методы. Методы в объектах — это функции, принадлежащие объекту.
Давайте создадим метод в классе Person.
Добавим функцию, которая выводит приветствие, и выполним ее:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def  myfunc(self):
        print("Привет, меня зовут "  + self.name)
        
p1 = Person("Василий", 36)
p1.myfunc()

Вывод:

Привет, меня зовут Василий

Параметр self

Параметр self является ссылкой на сам класс и используется для доступа к переменным, принадлежащим классу.
Его не обязательно называть self, вы можете называть его как хотите, но он должен быть первым параметром любой функции в классе.
Используем слова mysillyobject и abc вместо self:

class Person:
    def __init__(mysillyobject, name, age):
        mysillyobject.name = name
        mysillyobject.age = age
    
    def myfunc(abc):
        print("Привет, меня зовут "  + abc.name)


p1 = Person("Василий", 36)
p1.myfunc()

Вывод:

Привет, меня зовут Василий

Изменение свойств объекта

Вы можете изменять свойства объектов следующим образом.
Изменим возраст от p1 на 40:

p1.age = 40

Больше примеров применения class в Python 3: Примеры работы с классами в Python

Удалить свойства объекта

Свойства объектов можно удалять с помощью ключевого слова del

del p1.age

Удаление объектов

Вы можете удалить объекты, используя ключевое слово del.

del p1

Далее: Итераторы Python

]]>
Примеры работы с классами в Python https://pythonru.com/primery/primery-raboty-s-klassami-v-python Sat, 24 Nov 2018 13:43:12 +0000 https://pythonru.com/?p=668

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

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

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

class ClassName:
   """Необязательная строка документации класса"""  
   class_suite
  • У класса есть строка документации, к которой можно получить доступ через ClassName.__doc__.
  • class_suite состоит из частей класса, атрибутов данных и функции.

Пример создания класса на Python:

class Employee:  
    """Базовый класс для всех сотрудников"""  
    emp_count = 0  
  
    def __init__(self, name, salary):  
        self.name = name  
        self.salary = salary  
        Employee.emp_count += 1  
  
    def display_count(self):  
        print('Всего сотрудников: %d' % Employee.empCount)  
  
    def display_employee(self):  
        print('Имя: {}. Зарплата: {}'.format(self.name, self.salary))
  • Переменная emp_count — переменная класса, значение которой разделяется между экземплярами этого класса. Получить доступ к этой переменной можно через Employee.emp_count из класса или за его пределами.
  • Первый метод __init__() — специальный метод, который называют конструктором класса или методом инициализации. Его вызывает Python при создании нового экземпляра этого класса.
  • Объявляйте другие методы класса, как обычные функции, за исключением того, что первый аргумент для каждого метода self. Python добавляет аргумент self в список для вас; и тогда вам не нужно включать его при вызове этих методов.

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

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

# Это создаст первый объект класса Employee  
emp1 = Employee("Андрей", 2000)  
# Это создаст второй объект класса Employee  
emp2 = Employee("Мария", 5000) 

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

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

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

Теперь, систематизируем все.

class Employee:  
    """Базовый класс для всех сотрудников"""  
    emp_count = 0  
  
    def __init__(self, name, salary):  
        self.name = name  
        self.salary = salary  
        Employee.emp_count += 1  
  
    def display_count(self):  
        print('Всего сотрудников: %d' % Employee.emp_count)
        
    def display_employee(self):  
        print('Имя: {}. Зарплата: {}'.format(self.name, self.salary))  
  
  
# Это создаст первый объект класса Employee  
emp1 = Employee("Андрей", 2000)  
# Это создаст второй объект класса Employee  
emp2 = Employee("Мария", 5000)  
emp1.display_employee()  
emp2.display_employee()  
print("Всего сотрудников: %d" % Employee.emp_count)

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

Имя: Андрей. Зарплата: 2000
Имя: Мария. Зарплата: 5000
Всего сотрудников: 2

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

emp1.age = 7  # Добавит атрибут 'age'
emp1.age = 8  # Изменит атрибут 'age'
del emp1.age  # Удалит атрибут 'age'

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

  • getattr(obj, name [, default]) — для доступа к атрибуту объекта.
  • hasattr(obj, name) — проверить, есть ли в obj атрибут name.
  • setattr(obj, name, value) — задать атрибут. Если атрибут не существует, он будет создан.
  • delattr(obj, name) — удалить атрибут.
hasattr(emp1, 'age')  # возвращает true если атрибут 'age' существует
getattr(emp1, 'age')  # возвращает значение атрибута 'age' 
setattr(emp1, 'age', 8)  #устанавливает атрибут 'age' на 8
delattr(empl, 'age')  # удаляет атрибут 'age'

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

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

  • __dict__ — словарь, содержащий пространство имен класса.
  • __doc__ — строка документации класса. None если, документация отсутствует.
  • __name__ — имя класса.
  • __module__ — имя модуля, в котором определяется класс. Этот атрибут __main__ в интерактивном режиме.
  • __bases__ — могут быть пустые tuple, содержащие базовые классы, в порядке их появления в списке базового класса.

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

class Employee:  
    """Базовый класс для всех сотрудников"""  
    emp_count = 0  
  
    def __init__(self, name, salary):  
        self.name = name  
        self.salary = salary  
        Employee.empCount += 1  
  
    def display_count(self):  
        print('Всего сотрудников: %d' % Employee.empCount)  
  
    def display_employee(self):  
        print('Имя: {}. Зарплата: {}'.format(self.name, 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__: Базовый класс для всех сотрудников
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {'__module__': '__main__', '__doc__': 'Базовый класс для всех сотрудников', 'emp_count': 0, '__init__': <function Employee.__init__ at 0x03C7D7C8>, 'display_count': <function Employee.display_count at 0x03FA6AE0>, 'display_employee': <function Employee.display_employee at 0x03FA6B28>, '__dict__': <attribute '__dict__' of 'Employee' objects>, '__weakref__': <attribute '__weakref__' of 'Employee' objects>}

Удаление объектов (сбор мусора)

Python автоматически удаляет ненужные объекты (встроенные типы или экземпляры классов), чтобы освободить пространство памяти. С помощью процесса ‘Garbage Collection’ 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__()
Деструктор __del__() выводит имя класса того экземпляра, который должен быть уничтожен:

class Point:  
    def __init__(self, x=0, y=0):  
        self.x = x  
        self.y = y  
  
    def __del__(self):  
        class_name = self.__class__.__name__  
        print('{} уничтожен'.format(class_name))  
  
  
pt1 = Point()  
pt2 = pt1  
pt3 = pt1  
print(id(pt1), id(pt2), id(pt3))  # выведите id объектов  
del pt1  
del pt2  
del pt3

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

17692784 17692784 17692784
Point уничтожен

В идеале вы должны создавать свои классы в отдельном модуле. Затем импортировать их в основной модуль программы с помощью import SomeClass.

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

Наследование — это процесс, когда один класс наследует атрибуты и методы другого. Класс, чьи свойства и методы наследуются, называют Родителем или Суперклассом. А класс, свойства которого наследуются — класс-потомок или Подкласс.

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

Класс наследник наследует атрибуты своего родительского класса. Вы можете использовать эти атрибуты так, как будто они определены в классе наследнике. Он может переопределять элементы данных и методы родителя.

Синтаксис наследования класса

Классы наследники объявляются так, как и родительские классы. Только, список наследуемых классов, указан после имени класса.

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

Пример наследования класса в Python

class Parent:  # объявляем родительский класс  
    parent_attr = 100  
  
    def __init__(self):  
        print('Вызов родительского конструктора')  
  
    def parent_method(self):  
        print('Вызов родительского метода')  
  
    def set_attr(self, attr):  
        Parent.parent_attr = attr  
  
    def get_attr(self):  
        print('Атрибут родителя: {}'.format(Parent.parent_attr))  
  
  
class Child(Parent):  # объявляем класс наследник  
    def __init__(self):  
        print('Вызов конструктора класса наследника')  
  
    def child_method(self):  
        print('Вызов метода класса наследника')  
  
  
c = Child()  # экземпляр класса Child  
c.child_method()  # вызов метода child_method  
c.parent_method()  # вызов родительского метода parent_method  
c.set_attr(200)  # еще раз вызов родительского метода  
c.get_attr()  # снова вызов родительского метода

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

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

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

class A:        # объявите класс A
...

class B:        # объявите класс B
...

class C(A, B):  # C наследуется от A и B
...

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

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

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

Вы всегда можете переопределить методы родительского класса. В вашем подклассе могут понадобиться специальные функции. Это одна из причин переопределения родительских методов.

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

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

  
c = Child()  # экземпляр класса Child  
c.my_method()  # метод переопределен классом наследником

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

Вызов метода наследника

Популярные базовые методы

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

Метод, описание и пример вызова
1__init__(self [, args...]) — конструктор (с любыми необязательными аргументами)
obj = className(args)
2__del__(self) — деструктор, удаляет объект
del obj
3__repr__(self) — программное представление объекта
repr(obj)
4__str__(self) — строковое представление объекта
str(obj)

Пример использования __add__

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

Однако вы можете определить метод __add__ в своем классе для добавления векторов и оператор + будет вести себя так как нужно.

class Vector:   
    def __init__(self, a, b):   
        self.a = a   
        self.b = b   
    
    def __str__(self):    
        return 'Vector ({}, {})'.format(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)

Приватные методы и атрибуты

Атрибуты класса могут быть не видимыми вне определения класса. Вам нужно указать атрибуты с __ вначале, и эти атрибуты не будут вызваны вне класса.

Пример приватного атрибута:

class JustCounter:  
    __secret_count = 0  
  
    def count(self):  
        self.__secret_count += 1  
        print(self.__secret_count)  
  
  
counter = JustCounter()  
counter.count()  
counter.count()  
print(counter.__secret_count)

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

1
2
Traceback (most recent call last):
   File "test.py", line 12, in <module>
      print(counter.__secret_count)
AttributeError: 'JustCounter' object has no attribute '__secret_count'

Вы можете получить доступ к таким атрибутам, так object._className__attrName. Если вы замените свою последнюю строку следующим образом, то она будет работать.

...
print(counter._JustCounter__secret_count)

При выполнении кода, получаем результат:

1
2
2

Тест на понимание классов

Какое их представленных слов лучше всего подходит для названия класса?
Какое из следующих утверждений описывает эту строку?
xyz = Circle()
Как написать атрибут класса?
Как вызвать метод swim(5) у экземпляра hero?
Что происходит при наследовании Apple от Fruit?

]]>