Класс и объект в Python

Объектно-ориентированное программирование в 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']

Появились вопросы? Задайте на Яндекс Кью

У блога есть сообщество на Кью, подписывайтесь >> Python Q << и задавайте вопросы. Спрашивайте по контенту, про python и программирование в целом. Обещаю отвечать.

Вам помогла эта статья? Поделитесь в соцсетях или блоге. Репосты помогают сайту развиться.

Тест на знание python

Какой будет результат выполнения этого кода?
Какая функция разворачивает список задом наперед?
Какой будет результат выполнения этого кода?
Что выведет этот код?
Какие операторы можно использовать со строками?
Александр
Я создал этот блог в 2018 году, чтобы распространять полезные учебные материалы, документации и уроки на русском. На сайте опубликовано множество статей по основам python и библиотекам, уроков для начинающих и примеров написания программ.