object (объект)
Объекты — это экземпляры типов. Далее в этой статье речь пойдёт об использовании object в качестве базового класса. Понятие «объект» как таковое более подробно описано на странице «Объекты».
В отличие от классов старого стиля, объекты которых создавались на базе встроенного типа instance , классы нового стиля являются полноценными пользовательскими типами.
Для классов старого стиля type(x) выдаст instance — подразумевается, что класс не представляет собой самостоятельный тип, а лишь является экземпляром некого базового типа.
На заметку
object — это экземпляр типа type. Более того, обратное утверждение тоже верно. Это потому, что «всё — есть объект»: типы — это объекты, экземпляры типов — тоже объекты. Чтобы усугубить ощущение запутанности, скажем: тип — это подкласс объекта, однако обратное не верно.
isinstance(object, type) # True
isinstance(object, object) # True
isinstance(type, object) # True
isinstance(type, type) # True
issubclass(type, object) # True
issubclass(object, type) # False
Классы старого стиля упразднены в Python 3: теперь пользовательские типы, определённые без явного указания родителя, автоматически являются наследниками object . Переход на такую унифицированную объектную модель, помимо прочего, сделал возможным наследование от встроенных типов, применение дескрипторов, адекватное определение порядка разрешения методов при множественном наследовании.
# Следующие определения пользовательских типов
# эквивалентны.
# Python 2
class A(object): pass
# Python 3
class A: pass
Объекты
Объекты в Питоне — это абстракция над данными: любые данные здесь представлены объектами.
На заметку
За описанием типа object обратитесь к странице «object (объект)».
Примеры объектов в языке:
- Экземпляры пользовательских и встроенных типов;
- Сами типы;
- Байткод;
- Модули;
- Функции;
- и т.д.
На заметку
На уровне CPython объекты описываются при помощи базовой струтктуры PyObject .
Объекты обладают тремя базовыми (неотъемлемыми) характеристиками:
Идентификатор | Сущность, характеризующая объект, неизменна на протяжении всего периода существования объекта. Можно считать, что это адрес объекта в памяти. Идентичность двух объектов (по сути равенство идентификаторов) можно проверить при помощи оператора is . Получить идентификатор объекта можно при помощи функции id(). |
Тип | Тип данных определяет способности своих объектов и возможные значения для них. Подобно идентификатору тип остаётся неизменным на протяжении всего периода существования объекта. Получить тип объекта можно при помощи вызова type() с одним аргументом. Тип тоже является объектом, у которого тоже есть тип type. |
Значение | Если значение объекта может меняться, то объект называется изменяемым, если не может — неизменяемым. Изменяемость определяется типом: так числа, строки и кортежи — неизменяемы, в то время как словари и списки — изменяемы. |
Значение неизменяемого контейнера, содержащее ссылку на изменяемый объект, конечно, может меняться, когда этот объект изменяется. Однако сам контейнер, тем не менее, считается неизменяемым, потому как идентичность изменяемого объекта при этом не меняется (например, кортеж вполне может содержать [ссылку на] изменяемый объект).
Объектно-ориентированное программирование. Классы и объекты
Сегодня мы поговорим об объектно-ориентированном программировании и о его применении в python.
Объектно-ориентированное программирование (ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов.
Класс — тип, описывающий устройство объектов. Объект — это экземпляр класса. Класс можно сравнить с чертежом, по которому создаются объекты.
Python соответствует принципам объектно-ориентированного программирования. В python всё является объектами — и строки, и списки, и словари, и всё остальное.
Но возможности ООП в python этим не ограничены. Программист может написать свой тип данных (класс), определить в нём свои методы.
Это не является обязательным — мы можем пользоваться только встроенными объектами. Однако ООП полезно при долгосрочной разработке программы несколькими людьми, так как упрощает понимание кода.
Приступим теперь собственно к написанию своих классов на python. Попробуем определить собственный класс:
Теперь мы можем создать несколько экземпляров этого класса:
File
Классу возможно задать собственные методы:
И напоследок еще один пример:
Для вставки кода на Python в комментарий заключайте его в теги
- Модуль csv - чтение и запись CSV файлов
- Создаём сайт на Django, используя хорошие практики. Часть 1: создаём проект
- Онлайн-обучение Python: сравнение популярных программ
- Книги о Python
- GUI (графический интерфейс пользователя)
- Курсы Python
- Модули
- Новости мира Python
- NumPy
- Обработка данных
- Основы программирования
- Примеры программ
- Типы данных в Python
- Видео
- Python для Web
- Работа для Python-программистов
- Сделай свой вклад в развитие сайта!
- Самоучитель Python
- Карта сайта
- Отзывы на книги по Python
- Реклама на сайте
Объектно-ориентированное программирование
Python имеет множество встроенных типов, например, int, str и так далее, которые мы можем использовать в программе. Но также Python позволяет определять собственные типы с помощью классов . Класс представляет некоторую сущность. Конкретным воплощением класса является объект.
Можно еще провести следующую аналогию. У нас у всех есть некоторое представление о человеке, у которого есть имя, возраст, какие-то другие характеристики. Человек может выполнять некоторые действия - ходить, бегать, думать и т.д. То есть это представление, которое включает набор характеристик и действий, можно назвать классом. Конкретное воплощение этого шаблона может отличаться, например, одни люди имеют одно имя, другие - другое имя. И реально существующий человек будет представлять объект этого класса.
В языке Python класс определяется с помощью ключевого слова class :
class название_класса: атрибуты_класса методы_класса
Внутри класса определяются его атрибуты, которые хранят различные характеристики класса, и методы - функции класса.
Создадим простейший класс:
class Person: pass
В данном случае определен класс Person, который условно представляет человека. В данном случае в классе не определяется никаких методов или атрибутов. Однако поскольку в нем должно быть что-то определено, то в качестве заменителя функционала класса применяется оператор pass . Этот оператор применяется, когда синтаксически необходимо определить некоторый код, однако исходя из задачи код нам не нужен, и вместо конкретного кода вставляем оператор pass.
После создания класса можно определить объекты этого класса. Например:
class Person: pass tom = Person() # определение объекта tom bob = Person() # определение объекта bob
После определения класса Person создаются два объекта класса Person - tom и bob. Для создания объекта применяется специальная функция - конструктор , которая называется по имени класса и которая возвращает объект класса. То есть в данном случае вызов Person() представляет вызов конструктора. Каждый класс по умолчанию имеет конструктор без параметров:
tom = Person() # Person() - вызов конструктора, который возвращает объект класса Person
Конструкторы
Итак, для создания объекта класса используется конструктор. Так, выше когда мы создавали объекты класса Person, мы использовали конструктор по умолчанию, который не принимает параметров и который неявно имеют все классы. Однако мы можем явным образом определить в классах конструктор с помощью специального метода, который называется __init__() (по два прочерка с каждой стороны). К примеру, изменим класс Person, добавив в него конструктор:
class Person: # конструктор def __init__(self): print("Создание объекта Person") tom = Person() # Создание объекта Person
Итак, здесь в коде класса Person определен конструктор - функция __init__ . Конструктор должен принимать как минимум один параметр ссылку на текущий объект - self . Обычно конструкторы применяются для определения действий, которые должны производиться при создании объекта.
Теперь при создании объекта:
tom = Person()
выполняется вызов конструктора __init__() из класса Person, который выведет на консоль строку "Создание объекта Person".
Стоит отметить, что конструктор фактически представляет обычную функцию, только для вызовы конструктора используется не __init__ , а название класса. Кроме того, при вызове конструктора параметру self явным образом не передается никакого значения. При выполнении программы Python динамически будет определять self .
Атрибуты объекта
Атрибуты хранят состояние объекта. Для определения и установки атрибутов внутри класса можно применять слово self . Например, определим следующий класс Person:
class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека tom = Person("Tom", 22) # обращение к атрибутам # получение значений print(tom.name) # Tom print(tom.age) # 22 # изменение значения tom.age = 37 print(tom.age) # 37
Теперь конструктор класса Person принимает еще два параметра - name и age. Через эти параметры в конструктор будут передаваться имя и возраст создаваемого человека.
Внутри конструктора устанавливаются два атрибута - name и age (условно имя и возраст человека):
def __init__(self, name, age): self.name = name self.age = age
Атрибуту self.name присваивается значение переменной name. Атрибут age получает значение параметра age. Название атрибутов не обязательно должно соответствовать названиям параметров.
Если мы определили в классе конструктор __init__ с параметрами (кроме self), то при вызове конструктора этим параметрам надо передать значения:
tom = Person("Tom", 22)
То есть в данном случае параметру name передается строка "Tom", а параметру age - число 22.
Далее по имени объекта мы можем обращаться к атрибутам объекта - получать и изменять их значения:
print(tom.name) # получение значения атрибута name tom.age = 37 # изменение значения атрибута age
Подобным образом мы можем создавать разные объекты класса Person с разным значением для атрибутов:
class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека tom = Person("Tom", 22) bob = Person("Bob", 43) print(tom.name) # Tom print(bob.name) # Bob
Здесь создаются два объекта класса Person: tom и bob. Они соответствуют определению класса Person, имеют одинаковый набор атрибутов, однако их состояние будет отличаться. И в каждом случае Python будет динамически определять объект self. Так, в следующем случае
tom = Person("Tom", 22)
Это будет объект tom
bob = Person("Bob", 43)
Это будет объект bob
В принципе нам необязательно определять атрибуты внутри класса - Python позволяет сделать это динамически вне кода:
class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека tom = Person("Tom", 22) tom.company = "Microsoft" print(tom.company) # Microsoft
Здесь динамически устанавливается атрибут company, который хранит место работы человека. И после установки мы также можем получить его значение. В то же время подобное определение чревато ошибками. Например, если мы попытаемся обратиться к атрибуту до его определения, то программа сгенерирует ошибку:
tom = Person("Tom", 22) print(tom.company) # ! Ошибка - AttributeError: Person object has no attribute company
Методы классов
Методы класса фактически представляют функции, которые определенны внутри класса и которые определяют его поведение. Например, определим класс Person с одним методом:
class Person: # определение класса Person def say_hello(self): print("Hello") tom = Person() tom.say_hello() # Hello
Здесь определен метод say_hello() , который условно выполняет приветствие - выводит строку на консоль. При определении методов любого класса, как и конструктора, первый параметр метода представляет ссылку на текущий объект, который согласно условностям называется self . Через эту ссылку внутри класса мы можем обратиться к функциональности текущего объекта. Но при самом вызове метода этот параметр не учитывается.
Используя имя объекта, мы можем обратиться к его методам. Для обращения к методам применяется нотация точки - после имени объекта ставится точка и после нее идет вызов метода:
объект.метод([параметры метода])
Например, обращение к методу say_hello() для вывода приветствия на консоль:
tom.say_hello() # Hello
В итоге данная программа выведет на консоль строку "Hello".
Если метод должен принимать другие параметры, то они определяются после параметра self , и при вызове подобного метода для них необходимо передать значения:
class Person: # определение класса Person def say(self, message): # метод print(message) tom = Person() tom.say("Hello METANIT.COM") # Hello METANIT.COM
Здесь определен метод say() . Он принимает два параметра: self и message. И для второго параметра - message при вызове метода необходимо передать значение.
Для обращения к атрибутам и методам объекта внутри класса в его методах также применяется слово self:
self.атрибут # обращение к атрибуту self.метод # обращение к методу
Например, следующий класс Person:
class Person: def __init__(self, name, age): self.name = name # имя человека self.age = age # возраст человека def display_info(self): print(f"Name: Age: ") tom = Person("Tom", 22) tom.display_info() # Name: Tom Age: 22 bob = Person("Bob", 43) bob.display_info() # Name: Bob Age: 43
Здесь определяется метод display_info(), который выводит информацию на консоль. И для обращения в методе к атрибутам объекта применяется слово self: self.name и self.age
В итоге мы получим следующий консольный вывод:
Name: Tom Age: 22 Name: Bob Age: 43
Деструкторы
Кроме конструкторов классы в Python также могут определять специальные методы - деструкторы , которые вызываются при удалении объекта. Деструктор представляет собой метод __del__(self) , в который, как и в конструктор, передается ссылка на текущий объект. В деструкторе определяются действия, которые надо выполнить при удалении объекта, например, освобождение или удаление каких-то ресурсов, которые использовал объект.
Деструктор вызывается автоматически интерпретатором, нам не нужно его явным образом вызывать. Простейший пример:
class Person: def __init__(self, name): self.name = name print("Создан человек с именем", self.name) def __del__(self): print("Удален человек с именем", self.name) tom = Person("Tom")
Здесь в деструкторе просто выведится уведомление об удалении объекта Person. Программа создает один объект Person и хранит ссылку на него в переменной tom. Создание объекта вызовет выполнение конструктора. При завершении программы автоматически будет выполняться деструктор объекта tom. В итоге консольный вывод программы будет следующим:
Создан человек с именем Tom Удален человек с именем Tom
class Person: def __init__(self, name): self.name = name print("Создан человек с именем", self.name) def __del__(self): print("Удален человек с именем", self.name) def create_person(): tom = Person("Tom") create_person() print("Конец программы")
Здесь объект Person создается и используется внутри функции create_person, поэтому жизнь создаваемого объекта Person ограничена областью этой функции. Соответственно, когда функция завершит свое выполнение, у объекта Person будет вызываться деструктор. В итоге мы получим следующий консольный вывод:
Создан человек с именем Tom Удален человек с именем Tom Конец программы