Объекты и классы в Python
В этом руководстве вы познакомитесь с базовым функционалом объектов и классов Python. Что такое класс, как его создать и грамотно использовать в программе.
Python — объектно-ориентированный язык программирования. В отличие от процедурно-ориентированного программирования, ООП опирается на объекты.
Объект — это набор данных (переменных) и методов (функций), которые с этими данными взаимодействуют.
Представьте чертеж дома. В нем содержится вся информация: сколько этажей, какого размера двери, окна и т. д. На основе это чертежа мы можем построить дом. Дом — это объект.
По одному чертежу можно построить сразу несколько домов. Так же и с классом — по нему можно создать много объектов. Объект также можно назвать экземпляром класса, а процесс его создания — инстанцированием.
Как объявить класс
По аналогии с функциями, которые начинаются с def
, объявление класса сопровождается ключевым словом class
.
Первая строка внутри класса называется строкой документации, в ней содержится краткое описание класса. Писать ее рекомендуется, но не обязательно.
Объявим класс.
class MyNewClass: '''Это строка документации. Мы создали новый класс''' pass
Класс создает новое локальное пространство имен, где определяются все атрибуты. Атрибутами могут быть и переменные, и функции.
Есть и специальные атрибуты, которые начинаются с двойного нижнего подчеркивания __
. Например, __doc__
— строка документации класса.
После объявления класса создается объект этого класса с тем же именем. Этот объект класса позволяет нам как получить доступ к различным его атрибутам, так и инстанцировать новые объекты этого класса.
class Person: "Это класс, описывающий человека" age = 10 def greet(self): print('Привет') # Вывод: 10 print(Person.age) # Вывод: <function Person.greet at 0x7f32dbdbeee0> print(Person.greet) # Вывод: 'Это мой второй класс' print(Person.__doc__)
Вывод:
10
<function Person.greet at 0x7f32dbdbeee0>
Это класс, описывающий человека
Как создать объект
Мы уже знаем, что объект класса можно использовать для доступа к различным его атрибутам.
Использовать его можно и для создания новых экземпляров этого класса. Создание объекта похоже на вызов функции.
>>> harry = Person()
Так мы создадим новый экземпляр класса — harry
. Доступ к атрибутам объекта осуществляется при помощи префикса имени объекта.
Атрибутами могут быть и переменные, и методы. Методы объекта — функции этого класса.
Это значит следующее: Person.greet
— объект функции (атрибут класса), а harry.greet
— объект метода.
class Person: "Это класс, описывающий человека" age = 10 def greet(self): print('Привет') # создаем новый объект класса Person harry = Person() # Вывод: <function Person.greet> print(Person.greet) # Вывод: <bound method Person.greet of <__main__.Person object>> print(harry.greet) # Вызов метода greet() объекта # Вывод: Привет harry.greet()
Вывод:
<function Person.greet at 0x7fd288e4e160>
<bound method Person.greet of <__main__.Person object at 0x7fd288e9fa30>>
Привет
Возможно, вы заметили параметр self
в функции класса. Но вызывали метод мы с помощью
. И почему-то это сработало.
Так происходит потому, что когда объект вызывает свой метод, сам объект является первым аргументом. То есть harry.greet()
это то же самое, что и Person.greet(harry)
.
Обычно вызов метода со списком аргументов длины n
равносилен вызову соответствующей функции со списком аргументов, который создается путем вставки объекта метода перед первым аргументов.
По этим причинам первый аргумент функции в классе должен быть сам объект. Это и есть self
— так договорились программисты на Python. Но в теории можно использовать и другое обозначение.
Теперь вы имеете представление о классах, экземплярах класса, функциях, методах. Главное — понимать их отличия.
Конструкторы
Функции класса, начинающиеся с двойного нижнего подчеркивания, называются специальными функциями.
Наибольший интерес вызывает специальная функция __init__(
). Она вызывается каждый раз, когда вы создаете новый объект класса.
В ООП этот вид функций называют конструкторами. Обычно они используются для инициализации всех переменных класса.
class ComplexNumber: def __init__(self, r=0, i=0): self.real = r self.imag = i def get_data(self): print(f'{self.real}+{self.imag}j') # Создаем новый объект ComplexNumber num1 = ComplexNumber(2, 3) # Вызываем метод get_data() # Вывод: 2+3j num1.get_data() # Создаем еще один объект ComplexNumber # и новый атрибут 'attr' num2 = ComplexNumber(5) num2.attr = 10 # Вывод: (5, 0, 10) print((num2.real, num2.imag, num2.attr)) # У объекта c1 нет атрибута 'attr', поэтому # вызывается ошибка # AttributeError: 'ComplexNumber' object has no attribute 'attr' print(num1.attr)
Вывод:
2+3j
(5, 0, 10)
Traceback (most recent call last):
File "<string>", line 27, in <module>
print(num1.attr)
AttributeError: 'ComplexNumber' object has no attribute 'attr'
В этом примере мы объявили класс, представляющий комплексные числа. В нем две функции. Первая, __init__()
, инициализирует переменные (по умолчанию это нули). Вторая, get_data()
, позволяет правильно отображать числа в консоли.
Стоит отметить, что атрибуты объекта могут создаваться «на лету». Мы и создали, и считали атрибут attr
объекта num2
.
num1
.Как удалить атрибуты и объекты
Любой атрибут объекта можно в любой момент удалить. Сделать это можно с помощью оператора del
. Попробуйте запустить следующую программу и проверьте, что она выводит.
>>> num1 = ComplexNumber(2,3) >>> del num1.imag >>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'imag'
>>> del ComplexNumber.get_data >>> num1.get_data()
Traceback (most recent call last):
...
AttributeError: 'ComplexNumber' object has no attribute 'get_data'
С помощью del
можно удалить даже объект:
>>> c1 = ComplexNumber(1,3) >>> del c1 >>> c1
Traceback (most recent call last):
...
NameError: name 'c1' is not defined
На самом деле всё намного сложнее. Когда мы выполняем строку c1 = ComplexNumber(1,3)
, создается новый экземпляр класса. Переменная с1
является ссылкой на него.
После выполнения команды del
c1
ссылка и имя c1
Удаление объектов, на которые нет ссылок, называется сборкой мусора.
Создание классов и объектов. Урок 2 курса «Объектно-ориентированное программирование на Python»
В языке программирования Python классы создаются с помощью инструкции class, за которой следует произвольное имя класса, после которого ставится двоеточие, далее с новой строки и с отступом реализуется тело класса:
class ИмяКласса: код_тела_класса
Если класс является дочерним, то родительские классы перечисляются в круглых скобках после имени класса.
Объект создается путем вызова класса по его имени. При этом после имени класса обязательно ставятся скобки:
ИмяКласса()
То есть класс вызывается подобно функции. Однако в случае вызова класса происходит не выполнение его тела, как это происходило бы при вызове функции, а создается объект. Поскольку в программном коде важно не потерять ссылку на только что созданный объект, то обычно его связывают с переменной. Поэтому создание объекта чаще всего выглядит так:
имя_переменной = ИмяКласса()
В последствии к объекту обращаются через связанную с ним переменную.
Пример «пустого» класса и двух созданных на его основе объектов:
>>> class A: ... pass ... >>> a = A() >>> b = A()
Класс как пространство имен
С точки зрения пространства имен класс можно представить подобным модулю. Также как в модуле в классе могут быть свои переменные со значениями и функции. Также как в модуле у класса есть собственное пространство имен, доступ к которому возможен через имя класса:
>>> class B: . .. n = 5 ... def adder(v): ... return v + B.n ... >>> B.n 5 >>> B.adder(4) 9
Однако в случае классов используется особая терминология. Пусть имена, определенные в классе, называются атрибутами этого класса. В примере имена
Класс как шаблон для создания объектов
На самом деле классы – не модули. Они своего рода шаблоны, от которых создаются объекты-экземпляры. Такие объекты наследуют от класса его атрибуты. Вернемся к нашему классу B и создадим на его основе два объекта:
>>> class B: ... n = 5 ... def adder(v): ... return v + B. n ... >>> a = B() >>> b = B()
У объектов, связанных с переменными a и b, нет собственного поля n. Однако они наследуют его от своего класса:
>>> a.n 5 >>> a.n is B.n True
То есть поля a.n
и B.n
– это одно и то же поле, к которому можно обращаться и через имя a, и через имя b, и через имя класса. Поле одно, ссылок на него три.
Однако что произойдет в момент присваивания этому полю значения через какой-нибудь объект-экземпляр?
>>> a.n = 10 >>> a.n 10 >>> b.n 5 >>> B.n 5
В этот момент у экземпляра появляется собственный атрибут n, который перекроет (переопределит) родительский, то есть тот, который достался от класса.
>>> a.n is B.n False >>> b.n is B.n True
При этом присвоение через B.n
отразится только на b и B, но не на a:
>>> B. n = 100 >>> B.n, b.n, a.n (100, 100, 10)
Иная ситуация нас ожидает с атрибутом adder. При создании объекта от класса функция adder не наследуется как есть, а как бы превращается для объекта в одноименный метод:
>>> B.adder is b.adder False >>> type(B.adder) <class 'function'> >>> type(b.adder) <class 'method'>
Через имя класса мы вызываем функцию adder:
>>> B.adder(33) 133
Через имя объекта вызываем метод adder:
>>> b.adder(33) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: adder() takes 1 positional argument but 2 were given
В сообщении об ошибке говорится, что adder принимает только один аргумент, а было передано два. Откуда появился второй, если в скобках было указано только одно число?
Дело в том, что в отличии от функции в метод первым аргументом всегда передается объект, к которому применяется этот метод. То есть выражение b.adder(33)
как бы преобразовывается в adder(b, 33)
. Сам же b.adder
как объект типа method хранит сведения, с каким классом он связан и какому объекту-экземпляру принадлежит:
>>> b.adder <bound method B.adder of <__main__.B object at 0x7fcbf1ab9b80>>
В нашем случае, чтобы вызывать adder через объекты-экземпляры, класс можно переписать так:
>>> class B: ... n = 5 ... def adder(obj, v): ... return v + obj.n ... >>> b = B() >>> b.adder(33) 38
В коде выше при вызове метода adder переменной-параметру obj присваивается объект, связанный с переменной, к которой применяется данный метод. В данном случае это объект, связанный с b. Если adder будет вызван на другой объект, то уже он присвоится obj:
>>> a = B() >>> a.n = 9 >>> a. adder(3) 12
В Python принято переменную-параметр метода, которая связывается с экземпляром своего класса, называть именем self. Таким образом, более корректный код будет таким:
>>> class B: ... n = 5 ... def adder(self, v): ... return v + self.n
Можем ли мы все также вызывать adder как функцию, через имя класса? Вполне. Только теперь в функцию надо передавать два аргумента:
>>> B.adder(B, 200) 205 >>> B.adder(a, 200) 209
Здесь первым аргументом в функцию передается объект, у которого есть поле n лишь только потому, что далее к этому полю обращаются через выражение self.n
.
Однако если атрибут определен так, что предполагается его работа в качестве метода, а не функции, то через класс его уже не вызывают (нет смысла, логика программы этого не подразумевает).
С другой стороны, в ООП есть понятие «статический метод». По сути это функция, которая может вызываться и через класс, и через объект, и которой первым аргументом не подставляется объект, на который она вызывается. В Python статический метод можно создать посредством использования специального декоратора.
Атрибут __dict__
В Python у объектов есть встроенные специальные атрибуты. Мы их не определяем, но они есть. Одним из таких атрибутов объекта является свойство __dict__. Его значением является словарь, в котором ключи – это имена свойств экземпляра, а значения – текущие значения свойств.
>>> class B: ... n = 5 ... def adder(self, v): ... return v + self.n ... >>> w = B() >>> w.__dict__ {} >>> w.n = 8 >>> w.__dict__ {'n': 8}
В примере у экземпляра класса B сначала нет собственных атрибутов. Свойство n
и метод adder
– это атрибуты объекта-класса, а не объекта-экземпляра, созданного от этого класса. Лишь когда мы выполняем присваивание новому полю n
экземпляра, у него появляется собственное свойство, что мы наблюдаем через словарь __dict__.
В следующем уроке мы увидим, что свойства экземпляра обычно не назначаются за пределами класса. Это происходит в методах классах путем присваивание через self. Например, self.n = 10
.
Атрибут __dict__ используется для просмотра всех текущих свойств объекта. С его помощью можно удалять, добавлять свойства, а также изменять их значения.
>>> w.__dict__['m'] = 100 >>> w.__dict__ {'n': 8, 'm': 100} >>> w.m 100
Практическая работа
Напишите программу по следующему описанию. Есть класс «Воин». От него создаются два экземпляра-юнита. Каждому устанавливается здоровье в 100 очков. В случайном порядке они бьют друг друга. Тот, кто бьет, здоровья не теряет. У того, кого бьют, оно уменьшается на 20 очков от одного удара. После каждого удара надо выводить сообщение, какой юнит атаковал, и сколько у противника осталось здоровья. Как только у кого-то заканчивается ресурс здоровья, программа завершается сообщением о том, кто одержал победу.
Курс с примерами решений практических работ:
android-приложение, pdf-версия
Что такое метод класса в Python и зачем нужен.
Сразу начнем с примера простого класса, который содержит обычный метод и метод класса:
class MyClass: def method(self): return 'instance method called', self @classmethod def classmethod(cls): return 'class method called', cls
Как работают методы класса в Python?
В Python, методы класса отмечаются декоратором @classmethod
, следовательно в приведенном выше примере, метод класса будет определен в функции classmethod()
.
Как можно заметить, метод класса вместо того, чтобы принимать аргумент self
, принимает аргумент cls
. При вызове метода этот аргумент указывает на сам класс, а не на экземпляр класса.
Поскольку метод класса имеет доступ только к аргументу cls
, он не может изменять состояние экземпляра объекта. Для этого потребуется доступ к аргументу self
. НО все же методы класса могут изменять состояние класса, которое применяется ко всем экземплярам класса.
MyClass()
настроен таким образом, что реализация каждого метода возвращает кортеж для отслеживания, что происходит, и к каким частям класса или объекта метод может получить доступ.
Вот что происходит, когда мы вызываем метод экземпляра:
>>> obj = MyClass() >>> obj.method() # ('instance method called', <__main__.MyClass object at 0x7f9748403f40>) # Можно передать объект `obj` экземпляра вручную, # для получения того же результата >>> MyClass.method(obj) # ('instance method called', <__main__.MyClass object at 0x7f9748403f40>)
Этот кусок кода подтвердил, что метод экземпляра класса имеет доступ к экземпляру объекта, напечатанному как <__main__.MyClass object>
через аргумент self
.
Кстати, методы экземпляра также могут получить доступ к самому классу через атрибут self.__class__
. Это делает методы экземпляра мощными с точки зрения ограничений доступа — они могут изменять состояние как экземпляра объекта, так и самого класса.
Попробуем вызвать метод класса:
>>> obj.classmethod() # ('class method called', <class '__main__.MyClass'>)
Вызов метода класса obj.classmethod()
показал, что он не имеет доступа к объекту <__main__.MyClass object>
, а только к объекту <class '__main__.MyClass'>
, представляющему сам класс (в Python все является объектом, даже сами классы).
Обратите внимание, как Python автоматически передает класс в качестве первого аргумента функции, когда вызывается MyClass.classmethod()
. Вызов метода в Python через точечную нотацию запускает это поведение. Параметр self
в методах экземпляра работает точно так же.
Теперь посмотрим, что происходит, когда попытаться вызвать эти методы в самом классе — без предварительного создания экземпляра объекта:
>>> MyClass.classmethod() # ('class method called', <class '__main__.MyClass'>) >>> MyClass. method() # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: method() missing 1 required positional argument: 'self'
Из примера видно, что можно нормально вызвать метод класса MyClass.classmethod()
, но попытка вызвать метод экземпляра MyClass.method()
завершилась ошибкой TypeError
. Этого следовало ожидать, ведь экземпляр объекта не создан, что означает, что Python не может заполнить аргумент self
и следовательно, вызов не выполняется.
Для чего нужны методы класса в Python?
Следующие примеры кода должны сделать понимание метода класса более ясным. Далее рассмотрим пример класса, имеющего дело с информацией о дате (это будет шаблон):
class Date: def __init__(self, day=0, month=0, year=0): self.day = day self.month = month self.year = year def string_to_db(self): return f'{self.year}-{self.month}-{self.day}'
Этот класс, очевидно, можно использовать для хранения информации об определенных датах, без информации о часовом поясе (предположим, что все даты представлены в формате UTC).
Здесь есть конструктор __init__
, типичный инициализатор экземпляров классов Python, который получает аргументы как типичный метод экземпляра, имея первый необязательный аргумент self
, который содержит ссылку на вновь созданный экземпляр.
Например есть несколько задач, которые можно решить при помощи будущих методов этого класса, не только определенного для примера метода, банального перевода числовых значений в формат строки с датой для баз данных.
Предположим, что мы хотим создать много экземпляров класса Date()
с информацией о дате, поступающей из внешнего источника, в виде строки с форматом dd.mm.yyyy
. Предположим, нужно сделать это в разных местах исходного кода проекта.
Итак, что для этого необходимо сделать:
- Выполнить синтаксический анализ строки, получить день, месяц и год как три целочисленные переменные или кортеж из трех элементов, включающий эти переменные.
- Создать экземпляр
Date
, передав эти значения в конструктор класса при его создании.
Это будет выглядеть так:
>>> string_date = '10.10.2020' >>> day, month, year = map(int, string_date.split('.')) >>> date = Date(day, month, year) >>> date.string_to_db() # '2020-10-10'
Для выполнения этой задачи, например C++ или Java может реализовать такую возможность с перегрузкой метода __init__
, но в Python перегрузка методов отсутствует. Вместо нее необходимо использовать метод класса (декоратор @classmethod).
Создадим еще один «конструктор».
class Date(object): def __init__(self, day=0, month=0, year=0): self.day = day self.month = month self.year = year @classmethod def from_string(cls, date_as_string): day, month, year = map(int, date_as_string.split('.')) date1 = cls(day, month, year) return date1 def string_to_db(self): return f'{self.year}-{self.month}-{self.day}'
Более подробно о перегрузке смотрите в материале «Перегрузка методов в Python».
Обратите внимание, как используется аргумент cls
в методе класса from_string()
вместо прямого вызова конструктора класса Date()
.
Теперь создать новый экземпляр Date
, так же, можно следующим образом:
>>> date1 = Date.from_string('30.12.2020') >>> date1.string_to_db() # '2020-12-30' >>> date2 = Date.from_string('01.01.2021') >>> date2.string_to_db() # '2021-1-1'
Рассмотрим приведенную выше реализацию чтобы понять, какие преимущества здесь есть:
- Реализован синтаксический анализ строки даты в одном месте, и теперь его можно использовать повторно.
- Инкапсуляция здесь отлично работает. Если вы думаете, что можете реализовать синтаксический анализ строк как единственную функцию в другом месте, это решение намного лучше соответствует парадигме ООП.
cls
— это объект, который содержит сам класс, а не его экземпляр. Это довольно круто, потому что, если мы наследуем классDate
, для всех дочерних элементов также будет определен метод классаfrom_string()
.
Используя методы класса, можно добавить столько альтернативных конструкторов, сколько необходимо. Такое поведение может сделать интерфейс создаваемых классов самодокументированным (до определенной степени конечно) и упростить их использование.
Классы в Python
А давайте поговорим о классах в Python!
Объектно-ориентированный подход наиболее полезен, когда ваш код включает сложные взаимодействия многих объектов. В настоящем производственном коде классы могут иметь десятки атрибутов и методов со сложной логикой, но базовая структура такая же, как и в самом простом классе.
Классы подобны чертежам объектов, описывающим возможное поведение и состояния, которые может иметь каждый объект определенного типа. Например, если вы говорите, что «у каждого клиента будет номер телефона и адрес электронной почты, и он сможет размещать и отменять заказы», вы только что определили класс! Таким образом, вы можете говорить о клиентах в целом. Тогда конкретный объект Customer является просто реализацией этого класса с определенным значением состояния.
Поиск классов Python
В Python все является объектом. Числа, строки, датафреймы и даже функции являются объектами. В частности, все, с чем вы имеете дело в Python, имеет класс — шаблон, с которым под капотом связан этот объект. Благодаря наличию этих унифицированных интерфейсов вы можете, например, использовать любой DataFrame одним и тем же образом.
Вы можете вызвать функцию type()
для любого объекта Python, чтобы узнать его класс. Например, класс массива numpy на самом деле называется ndarray
(для n-мерного массива). Это показано в коде ниже:
import numpy as np a = np.array([1,2,3,4]) print(type(a)) # numpy.ndarray
Классы включают информацию о состоянии объекта и его поведении. Информация о состоянии объекта в Python содержится в атрибутах, а информация о его поведении — в методах.
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Подробнее
×
Атрибуты и методы
Давайте возьмем массив numpy. Мы уже использовали некоторые его методы и атрибуты!
К примеру, у каждого массива numpy есть атрибут shape
, к которому вы можете получить доступ, указав имя массива, за которым следуют точка и название атрибута shape
.
Состояние <—> Атрибуты
Выглядеть это будет следующим образом:
import numpy as np a = np. array([1,2,3,4]) # shape attribute a.shape # (4,)
У массива numpy также есть такие методы, как max
и reshape
, которые точно также доступны через точку.
Поведение <—> Методы
Использование метода для класса массивов numpy будет выглядеть, к примеру, так:
import numpy as np a = np.array([1,2,3,4]) # reshape method a.reshape(2,2) # array([[1, 2], # [3, 4]])
Создание вашего первого класса
Время написать свой первый класс! В этом упражнении мы создадим пустой класс Employee
. Затем создадим объект emp
класса Employee
, вызвав наш класс Employee()
. Выглядеть это будет следующим образом:
# Create an empty class Employee class Employee: pass # Create an object emp of class Employee emp = Employee()
Отлично! А теперь попробуйте распечатать атрибут . name
объекта emp
в консоли. Что получается?
emp.name # Traceback (most recent call last): # File "main.py", line 6, in <module> # emp.name # AttributeError: 'Employee' object has no attribute 'name'
Код выдаст вам ошибку, потому что атрибут .name
не существует. И это действительно так, ведь мы не задали такой атрибут для нашего класса Employee
.
Давайте дополним наш код следующим образом:
class Employee: def __init__(self, name): self.name = name # Create an object emp of class Employee emp = Employee('John') print(emp. name)
А теперь давайте снова попробуем вывести атрибут .name
:
John
Вуаля! Всё работает. Мы получили имя нашего работника John
. Ведь в этот раз мы сами задали атрибут name
для нашего класса Employee
.
Однако мы можем пойти дальше и написать функцию, которая позволит нам изменить имя нашего сотрудника. Выглядеть это может следующим образом:
class Employee: def __init__(self, name): self.name = name def set_name(self, new_name): self.name = new_name emp = Employee('John') emp.set_name('Korel Rossi') print(emp. name)
Давайте запустим наш код и увидим, что теперь значение атрибута .name
изменилось на следующее:
Korel Rossi
Заключение
Итак, сегодня мы поговорили про классы в Python. Обсудили основы того, что такое класс и как его создать. Кроме того, мы также разобрали, что такое атрибуты и методы класса.
Надеемся, данная статья была вам полезна! Успехов в написании кода!
Перевод статьи «Python Classes».
Английский для программистов
Наш телеграм канал с тестами по английскому языку для программистов. Английский это часть карьеры программиста. Поэтому полезно заняться им уже сейчас
Подробнее
×
Классы: введение в объектно-ориентированное программирование
Классы: введение в объектно-ориентированное программированиеСсылки и объекты
Представление переменных в языке Python сильно отличается от традиционных
языков программирования: Pascal, C, Java. Любая сущность, с которой работает
Python-программа, является объектом. Числа, строки, списки, множества
являются объектами. Названия функций также являются объектами и в некотором
смысле ничем не отличаются от чисел, кроме того, что у функций есть операции,
нетипичные для чисел (например, вызов функции при помощи операции ()
), а другие операции, наоборот, отсутствуют.
У каждого объекта есть свой тип (это также называется классом): int
, str
, set
, function
и т.д.
Переменные в свою очередь являются ссылками на объекты: в любой момент времени переменная связана с каким-то объектом в памяти. Если мы выполняем присваивание:
a = 5
то имя переменной 5
связывается с объектом типа int
, в котором хранится значение 5.
Если теперь выполнить другое присваивание:
a = 'hello'
то старая связь разрывается, создается новый объект типа str
, в котором хранится значение 'hello'
,
и переменная a
связывается с этим объектом.
Если же теперь выполнить операцию:
def a(): pass
то в памяти создается объект типа function
,
хранящий тело функции из одной инструкции pass
,
и переменная a
теперь связывается с этой функцией.
Если же справа от оператора =
поставить
имя другого объекта:
b = a
то второй объект связывается с тем же объектом, с которым
был связан первый объект: теперь b
и a
становятся ссылками на один и тот же объект и являются неразличимыми,
пока для одного из них связь не будет разорвана при помощи оператора =
Интересным свойством является то, что переменные могут ссылаться
на один и тот же объект. Проверить, ссылаются ли две переменные
на один объект или на разные можно при помощи оператора is
, возвращающего значение True
,
если ссылки совпадают:
a is b
При этом переменные могут ссылаться на различные, но равные
объекты, то есть оператов ==
для них вернет True
. Пример различных, но равных объектов:
a = 'a' * 1000 b = 'aa' * 500
Но при этом в целях экономии памяти если переменным присвоить значение одного и того же небольшого целого числа или одной и той же небольшой строки, то переменные будут ссылаться на один и тот же объект, даже если значение этого объекта будет получено разными путями. Например:
a = 2 + 3 b = 1 + 4
При выполнении второго оператора =
, интерпретатор
обнаружит, что в памяти уже есть объект со значением 5
и не будет создавать другой объект с таким же значением.
Такое повторное использование применяется только для небольших чисел,
строк и объектов типа bool
, поскольку для больших объектов
проверка того, что объект уже хранится в памяти требует много времени.
Создание новых типов данных
Часто программе приходится иметь дело не с простыми числовыми и строковым данными, а с более сложными объектами, являющихся представлением каких-то жизненных сущностей.
Например, пусть программе дан список учащихся, который нужно отсортировать по экзаменационному баллу. Это можно сделать, если хранить в одном списке имена учащихся, в другом списке их баллы, и сортировать список баллов, синхронно переставляя элементы в списке имен учащихся. Такой путь, очевидно, неудобен.
Можно использовать кортеж, один из элементов которого будет равен имени учащегося, другой элемент — его баллу. Такой подход лучше тем, что позволяет работать с представлением одного учащегося, как с единым целым, что экономит действия, например, при сортировке, и повышает наглядность программы.
В этом случае придется поставать так:
Vasya = ('Василий', 4) print('Имя:', Vasya[0]) print('Балл:', Vasya[1])
Но элементы кортежей не имеют собственных названий (то есть вовсе неочевидно, балл хранится именно в элементе кортежа с индексом 1). Удобней было бы обозначить атрибуты каждого объекта какими-то осмысленными идентификаторами и далее работать с этими идентификаторами. Пример:
class Person: pass Vasya = Person() Vasya.name = 'Василий' Vasya.score = 4
В этом примере мы объявляем новый класс объектов: Person
.
Затем мы создаем новый объект класса, при помощи вызова конструктора Person()
, который возвращает ссылку на новый объект, и присваиваем
ссылку на этот объект переменной Vasya
, которая также называется
экземпляром класса или объектом. Далее объекту Vasya
устанавливается
два атрибута: name
(типа str
) и score
(типа int
).
Поля и методы
Таким образом, объе ты классов представляют собой новые типы данный, объединяющие
несколько атрибутов (полей). Атрибуты могут быть произвольными типами данных:
числами, строками, списками, множествами, словарями, другими классами.
Обращение к атрибуту какого-либо объекта осуществляется при помощи dot-нотации: имя_класса.имя_атрибута
.
Помимо полей у классов бывают методы: функции, которые можно применять
к экземплярам класса. Например, у списков есть метод sort
.
Вызов метода также осуществляется при помощи dot-нотации, например: A.sort()
.
Можно рассматривать методы, как функции, у которых первым параметром является
экземпляр класса. Методы так и объявляются: как функции внутри описания класса,
первым параметром которой является экземпляр класса. По соглашению,
эта ссылка должна называться self
. Вот пример объявления
класса Person
и метода print
, выводящего
информацию о полях name
и score
:
class Person: def print(self): print(self.name, self.score)
Теперь для вызова метода print
для объекта Vasya
нужно вызвать Vasya.print()
. При этом не нужно задавать
первый параметр self
: в качестве этого параметра автоматически
будет передан объект, для которого был вызван метод.
Методы могут принимать дополнительные параметры, как и обычные функции. Эти параметры описываются после параметра self
.
Стандартные методы
Наш метод print
предполагает, что у объекта есть
поля name
и score
, иначе он завершится
с ошибкой. Хочется быть уверенным, что у любого объекта класса Person
есть эти поля. Для этого проще всего создать
эти поля при создании объекта, т.е. при вызове функции Person
.
Для этого можнзо использовать конструктор: метод, который
автоматически вызывается при создании объекта. Конструктором
является метод с именем __init__
:
class Person: def __init__(self): self.name = '' self.score = 0
При создании объекта функцией Person
будет автоматически вызван конструктор __init__
(явно вызывать его не нужно), который полю name
объекта, для которого он вызван, присвоит пустую строку,
а полю score
присвоит значение 0.
Удобно будет, если конструктор сможет создавать объект, инициализируя поля объекта некоторыми параметрами, используя передаваемые ему значения, а не значения по умолчанию. Для этого конструктору можно передавать параметры:
class Person: def __init__(self, name, score): self.name = name self.score = score
В данном случае мы используем одинаковые имена (name
, score
) для обозначения передаваемых параметров и полей
класса. Это сделано для удобства — имена могут и различаться.
Теперь мы сможем создавать новый объект с заданными полями
так: Person('Иванов', 5)
.
Но поскольку конструктор теперь обязательно принимает два дополнительных параметра мы лишились возможности вызывать конструктор без параметров, что также бывает удобно. Можно вернуть эту особенность, если установить для параметров, передаваемых конструктору, значения по умолчанию:
class Person: def __init__(self, name = '', score = 0): self.name = name self.score = score
Теперь мы можем вызывать конструктор как с параметрами
(Person('Иванов', 5)
), так и без параметров
(Person()
), в последнем случае параметрам
будут переданы значения “по умолчанию”, указанные
в описании конструктора.
Есть и другие стандартные методы, которые можно определить в описании класса.
Метод __repr__
должен возвращать текстовую
строку, содержащую код (на языке Python), создающую объект,
равный данному. Естественно, метод __repr__
должен содержать вызов конструктора, которому передаются
в качестве параметров все строки исходного объекта,
то есть он должен возвращать строку вида "Person('Иванов', 5)"
Пример метода __repr__
(для экономии
места опустим описание конструктора __init__
):
class Person: def __repr__(self): return "Person('" + self.name + "', " + self.score + ")"
Таким образом, метод __repr__
возвращает строку с описанием
объекта, которое может быть воспринято итерпретатором языка Питон.
Метод __str__
возвращает строку, являющуюся
описанием объекта в том виде, в котором его удобно будет воспринимать
человеку. Здесь не нужно выводить имя конструктора, можно, например,
просто вернуть строку с содержимым всех полей:
class Person: def __str__(self): return self. name + ' ' + str(self.score)
Метод __str__
будет вызываться, когда вызывается функция str
от данного объекта, например, str(Vasya)
.
То есть создавая метод __str__
вы даете указание
Питону, как преобразовывать данный объект к типу str
.
Поскольку функция print
использует именно функцию str
для вывода объекта на экран, то определение
метода __str__
позволит выводить объекты на экран
удобным способом: при помощи print
.
Переопределение стандартный операций
Рассмотрим класс Point
(точка), используемый
для представления точек (или радиус-векторов) на координатной
плоскости. У точки два естественных поля-координаты: x
и y
. Если рассматривать точку как радиус-вектор, то хотелось
бы определить для точек операцию +
, чтобы точки можно было
складывать столь же удобно, как и числа или строки. Например, чтобы
можно было записать так:
A = Point(1, 2) B = Point(3, 4) C = A + B
Для этого необходимо перегрузить операцию +
:
определить функцию, которая будет использоваться, если операция +
будет вызвана для объекта класса Point
. Для этого нужно определить
метод __add__
класса Point
, у которого два
параметра: неявная ссылка self
на экземпляр класса, для которого
она будет вызвана (это левый операнд операции +
) и явная ссылка other
на правый операнд:
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __add__(self, other): return Point(self.x + other.x, self.y + other.y)
Теперь при вызове оператора A + B
Питон
вызовет метод A.__add__(B)
, то есть вызовет
указанный метод, где self = A
, other = B
.
Аналогично можно определить и оставшиеся операции. Полезной
для переопределения является операция <
.
Она должна возвращать логическое значение True
,
если левый операнд меньше правого или False
в противном случае (также в том случае, если объекты равны).
Для переопределения этого операнда нужно определить метод __lt__
(less tthan):
class Point: def __lt__(self, other): return self. x < other.x or self.x == other.x and self.y < other.y
В этом примере оператор вернет True
, если у левого операнда
поле x
меньше, чем у правого операнда, а также если поля x
у них равны, а поле y
меньше у левого операнда.
После определения оператора <
, появляется возможность упорядочивать
объекты, используя этот оператор. Теперь можно сортировать списки объектов
при помощи метода sort()
или функции sorted
,
при этом будет использоваться именно определенный оператор сравнения <
.
Функции
type
и isinstance
Полезно, чтобы конструктор __init__
мог воспринимать
параметры различных типов. Например, удобно инициализировать
точку не только двумя числами, но и строкой, в которой через
пробел записаны два числа (такая строка может быть считана со стандартного ввода),
списком или кортежем. То есть передаваемые конструктору аргументы могут быть
разного типа (int
, float
, str
, list
, tuple
). Конструктор должен выполнять различные действия для
параметров различного типа, для этого нужно уметь проверять принадлежность
объекту какому-либо классу.
Эту задачу можно решить при помощи функций type
и isinstance
. Функция type
возвращает
класс, к которому принадлежит объект. Например:
if type(a) == int: print('a - целое число') elif type(a) == str: print('a - строка')
Для этого можно использовать функцию isinstance
,
у которой два параметра: объект и класс. Функция возращает True
, если объект принадлежит классу
или False
в противном случае. Пример:
if isinstance(a, int): print('a - целое число') elif isinstance(a, str): print('a - строка')
Список возможных перегружаемых операторов
Полная документация на английском: http://docs.python.org/py3k/reference/datamodel.html.
Следующая таблица взята из книги Саммерфильда (стр. 283 и далее).
Метод | Использование |
---|---|
Операторы сравнения | |
__lt__(self, other) | x < y |
__le__(self, other) | x <= y |
__eq__(self, other) | x == y |
__ne__(self, other) | x != y |
__gt__(self, other) | x > y |
__ge__(self, other) | x >= y |
Арифметические операторы | |
Сложение | |
__add__(self, other) | x + y |
__radd__(self, other) | y + x |
__iadd__(self, other) | x += y |
Вычитание | |
__sub__(self, other) | x - y |
__rsub__(self, other) | y - x |
__isub__(self, other) | x -= y |
Умножение | |
__mul__(self, other) | x * y |
__rmul__(self, other) | y * x |
__imul__(self, other) | x *= y |
Деление | |
__truediv__(self, other) | x / y |
__rtruediv__(self, other) | y / x |
__itruediv__(self, other) | x /= y |
Целочисленное деление | |
__floordiv__(self, other) | x // y |
__rfloordiv__(self, other) | y // x |
__ifloordiv__(self, other) | x //= y |
__divmod__(self, other) | divmod(x, y) |
Остаток | |
__mod__(self, other) | x % y |
__rmod__(self, other) | y % x |
__imod__(self, other) | x %= y |
Возведение в степень | |
__pow__(self, other) | x ** y |
__rpow__(self, other) | y ** x |
__ipow__(self, other) | x **= y |
Отрицание, модуль | |
__pos__(self) | +x |
__neg__(self) | -x |
__abs__(self) | abs(x) |
Преобразование к стандартным типам | |
__int__(self) | int(x) |
__float__(self) | float(x) |
__str__(self) | str(x) |
__round__(self, digits = 0) | round(x, digits) |
Упражнения
Класс “Точка” (Point)
Создайте класс Point
, определите для него конструктор,
метод __str__
, необходимые арифметические операции. У класса Point
два поля: x
и y
.
A: Самая дальняя точка
Программа получает на вход число N, далее координаты N точек. Выведите координаты точки, наиболее удаленной от начала координат.
Для решения этой задачи напишите метод dist
,
который возвращает расстояние от точки до начала координат.
Ввод | Вывод |
---|---|
2 | 2 3 |
B: Центр масс
Выведите координаты центра масс данного множества точек (учтите, что это —два действительных числа).
Для создания точки определите конструктор, который мог бы
принимать на вход как два числа, так и строку. Таким образом,
точку можно будет создавать как вызовом Point(x, y)
,
так и Point(input())
.
Определите метод __str__
для вывода точки. Определите операции сложения точек, умножения точки на число,
деления точки на число.
Ввод | Вывод |
---|---|
2 | 1.5 2.5 |
C: Диаметр множества
Выведите диаметр данного множества – максимальное расстояние между двумя данными точками.
Для этого удобно определить операцию разности двух точек, возвращающую разность двух радиус-векторов, затем вызывать метод, вычисляющий длину данного радиус-вектора.
Ввод | Вывод |
---|---|
3 | 1.4142135623731 |
D: Сортировка
Определите для точек операцию сравнения __lt__
, сравнивающую
точки по значению расстояния от начала координат. Отсортируйте данные
точки в порядке возрастания расстояния от начала координат.
Ввод | Вывод |
---|---|
3 | 0 0 |
E: Максимальный периметр
Среди данных точек найдите три точки, образующие треугольник с наибольшим периметром. Выведите данный периметр.
Для нахождения периметра треугольника напишите отдельную функцию Perimeter(A, B, C)
.
Ввод | Вывод |
---|---|
4 | 3.41421356237309 |
F: Максимальная площадь
Среди данных точек найдите три точки, образующие треугольник с наибольшей площадью. Выведите данную площадь.
Для нахождения площади треугольника напишите отдельную функцию Area(A, B, C)
.
Ввод | Вывод |
---|---|
4 | 0.5 |
Класс “Дробь” (Fraction)
Класс Fraction
должен иметь два поля: числитель a
и
знаменатель b
. Оба поля должны быть типа int
.
Для класса Fraction
определите конструктор, который может
принимать следующие виды параметров:
- Ни одного параметра (в этом случае дробь должна быть равна 0).
- Один параметр типа
Fraction
. - Один параметр типа
int
. - Два параметра типа
int
. - Один параметр типа
str
, содержащий два целых числа, записанных либо через пробел, либо через дробную черту или одно целое число.
У каждой дроби существует единственное каноническое представление. Каноническое представление: это такое представление \(\frac{a}{b}\), что
\(b>0\), \( (a, b) = 1\). Класс должен иметь метод reduce
,
который приводит дробь к каноническому представлению. После каждой операции
с дробями (в том числе и в конструкторе) необходимо вызывать метод reduce
для сокращения дроби.
Необходимо определить метод __str__
, который выводит a/b
в каноническом представлении, если же дробь является целым
числом, то просто значение этого числа.
G: Сократите дробь
Каждая строка входного файла содержит либо два числа, записанных через пробел или
дробную черту, либо одно число. Необходимо считать это число в строку и вызвать
конструктор для считанной строки, получив объект класса Fraction
.
После этого нужно вывести данный объект функцией print
Ввод | Вывод |
---|---|
1 2 | 1/2 |
H: Конструкторы
Напомним, что от вас требовалось реализовать конструктор класса Fraction
, который принимает на вход
разные варанты параметров. В этой задаче проверяется реализация всех этих четырех форм конструктора.
Программа получает на вход текст программы на питоне, использующий различные формы конструктора Fraction
и вывод объекта Fraction
при помощи функции print
. Ваша программа должна считать этот текст
и исполнить его при помощи интерпретатора Питона. Это делается так:
exec(stdin.read())
Ввод | Вывод |
---|---|
a = Fraction() | 0 |
I: Сравнения
Определите методы __lt__
, __le__
, __gt__
, __ge__
, __eq__
, __ne__
. В качестве параметра other
может выступать объект
одного из трех типов: int
, float
, Fraction
.
Тестирование проводится, как в предыдущей задаче.
J: Умножение
Определите методы умножения __mul__
, __rmul__
, __imul__
так, чтобы
можно было:
- Вычислять произведение двух дробей.
- Вычислять произведение дроби и
int
(результатом является дробь), а такжеint
и дроби. - Вычислять произведение дроби и
float
(результатом являетсяfloat
), а такжеfloat
и дроби. - Умножать объект класса
Fraction
наFraction
илиint
.
Методы типа __imul__
, то есть переопределяющие
операторы присваивания (*=
) должны возвращать self
.
K: Деление
Определите методы деления __truediv__
, __rtruediv__
, __itruediv__
.
L: Возведение в степень
Определите операции возведения в степень __pow__
, __rpow__
так, чтобы можно было
возводить дроби в степень типа int
, float
, Fraction
, числа типа int
и float
в степень Fraction
. Операция возведения Fraction ** int
возвращает Fraction
, во всех остальных случаях возвращается float
.
Определите операцию __ipow__
для возведения дроби в целочисленную степень.
M: Сложение
Определите операции __add__
, __iadd__
, __radd__
.
N: Вычитание
Определите операции __sub__
, __isub__
, __rsub__
.
O: Знаки
Определите операции __pos__
, __neg__
, __abs__
.
P: Преобразование типов
Определите операции __int__
(должна округлять вниз до ближайшего целого), __float__
, __round__
(должна возвращать значение типа float
,
можно использовать функцию round
для величины типа float
).
Создание класса в Python: атрибуты и методы
Эксперименты будем ставить на коде, который решает очень важную и ответственную задачу — выводит на экран вес фруктов. Делает он это, разумеется, с использованием ООП. Куда же без него во “взрослых” проектах?! И пускай от объявленного класса Fruit
нет никакого проку, без него код выглядел бы слишком просто, а теперь в самый раз:
class Fruit(): pass apple = Fruit() apple.fruit_name = 'Яблоко' apple.weight_kg = 0.1 orange = Fruit() orange.fruit_name = 'Апельсин' orange.weight_kg = 0.3 print(apple.fruit_name, "| вес в граммах", apple.weight_kg * 1000) print(orange.fruit_name, "| вес в граммах", orange.weight_kg * 1000)
Скопируйте код к себе, запустите его в консоли:
$ python script.py Яблоко | вес в граммах 100.0 Апельсин | вес в граммах 300.0
Как это работает
Разберем что написано в этом коде. Первые две строки объявят новый класс Fruit
:
class Fruit(): pass
Команда pass
ничего не делает. Это заглушка, она нужна лишь потому, что Python требует внутри объявления класса написать хотя бы какой-то код. Написать здесь нечего, поэтому pass
.
Следующая строка кода создаст новый объект — яблоко “apple”:
apple = Fruit()
Класс Fruit
выступает шаблоном, который описывает свойства общие сразу для всех фруктов: и для яблок, и для апельсинов. Пока что шаблон пуст, и экземпляр apple
ничего полезного от вызова Fruit
не получит.
Следующие две строки добавят пару атрибутов к яблоку — название фрукта и его вес:
apple.fruit_name = 'Яблоко' apple.weight_kg = 0.1
Затем аналогичным образом по тому же шаблону — классу Fruit
— будет создан еще один фрукт, на этот раз апельсин:
orange = Fruit() orange.fruit_name = 'Апельсин' orange.weight_kg = 0.3
Последние строчки кода пересчитают вес фрукта в граммах и выведут в консоль название и вес:
print(apple.fruit_name, "| вес в граммах", apple.weight_kg * 1000) print(orange.fruit_name, "| вес в граммах", orange.weight_kg * 1000)
Обязательные атрибуты
Можно заметить, что оба фрукта в программе имеют свойства с одинаковыми названиями — название fruit_name
и вес weight_kg
. Доработаем класс Fruit
таким образом, чтобы все экземпляры созданные по этому шаблону обязательно имели свойства fruit_name
и weight_kg
.
Идея следующая. Пусть Python каждый раз после создания нового экземпляра фрукта сразу добавляет все нужные атрибуты. Добавим для этого новую функцию init_attrs
:
# ... объявление класса Fruit ... def init_attrs(fruit, fruit_name='неизвестный фрукт', weight_kg=None): fruit.fruit_name = fruit_name fruit.weight_kg = weight_kg apple = Fruit() init_attrs(apple, 'Яблоко', 0.1) orange = Fruit() init_attrs(orange, 'Апельсин', 0.3) # ... вызовы print ...
Кода стало больше, но он стал надежнее. Добавляя новые фрукты: груши, вишню или абрикосы — вы точно не забудете указать вес и название. Вызовы функции init_attrs
гарантирует, что все фрукты получат одинаковый набор обязательных атрибутов.
В Python коде функции похожие на init_attrs
встречаются настолько часто, что для них есть стандартное название и специальный синтаксис. Переименуем функцию init_attrs
в __init__
и переместим внутрь класса Fruit
.
class Fruit(): def __init__(fruit, fruit_name='неизвестный фрукт', weight_kg=None): fruit.fruit_name = fruit_name fruit.weight_kg = weight_kg apple = Fruit('Яблоко', 0.1) orange = Fruit('Апельсин', 0.3) print(apple.fruit_name, "| вес в граммах", apple.weight_kg * 1000) print(orange.fruit_name, "| вес в граммах", orange.weight_kg * 1000)
Обратите внимание, что в программе нигде нет явного вызова __init__
. Python сам его вызовет выполняя эти строки кода:
apple = Fruit('Яблоко', 0.1) orange = Fruit('Апельсин', 0.3)
Теперь создавать фрукты по шаблону стало еще проще. Не надо писать вызовы функций, достаточно передать все аргументы для __init__
в класс Fruit
.
Часто метод __init__
называют конструктором класса по аналогии с другими языками программирования. Это не совсем верно. Подробнее читайте на StackOverflow.
Добавим метод
Можно заметить что в коде пару раз встречается одинаковое выражение для расчета веса в граммах:
print(..., apple.weight_kg * 1000) print(..., orange.weight_kg * 1000)
Пересчет веса можно вынести в отдельную функцию:
# ... объявление класса, __init__ для Fruit def get_weight_gr(fruit): return fruit.weight_kg * 1000 apple = Fruit('Яблоко', 0.1) orange = Fruit('Апельсин', 0.3) print(apple.fruit_name, "| вес в граммах", get_weight_gr(apple)) print(orange.fruit_name, "| вес в граммах", get_weight_gr(orange))
Функция get_weight_gr
требует единственный аргумент — объект описывающий фрукт. Ей нет разницы, с каким именно фруктом работать, яблоком или апельсином. Главное, это чтобы фрукт был создан по стандартному шаблону — на основе класса Fruit
. Python позволяет спрятать функцию get_weight_gr
внутрь класса Fruit
, чтобы эту связь между ними было не разорвать.
class Fruit(): def __init__(fruit, fruit_name='неизвестный фрукт', weight_kg=None): fruit.fruit_name = fruit_name fruit.weight_kg = weight_kg def get_weight_gr(fruit): return fruit.weight_kg * 1000
Функции, объявленные внутри класса называют методами и Python предлагает специальный набор инструментов для работы с ними.
По аналогии с функциями метод можно вызвать так:
Fruit.get_weight_gr(apple)
Однако, не вдаваясь в детали, принято делать так:
apple.get_weight_gr()
Python всегда помнит от какого класса был создан тот или иной объект, и знает что яблоко apple
принадлежит к классу Fruit
. От класса Fruit
яблоко apple
получило все его методы, включая get_weight_gr
. Доступ к методам объекта получают через точку apple.get_weight_gr
, а при вызове указывают первый аргумент функции, потому что его автоматически подставляет Python.
Теперь программа выглядит так:
class Fruit(): def __init__(fruit, fruit_name='неизвестный фрукт', weight_kg=None): fruit. fruit_name = fruit_name fruit.weight_kg = weight_kg def get_weight_gr(fruit): return fruit.weight_kg * 1000 apple = Fruit('Яблоко', 0.1) orange = Fruit('Апельсин', 0.3) print(apple.fruit_name, "| вес в граммах", apple.get_weight_gr()) print(orange.fruit_name, "| вес в граммах", orange.get_weight_gr())
Кто такой
self
В Python есть стандартное название для первого атрибута метода. Вернемся к коду с фруктами и увидим там такое объявление методов:
class Fruit(): def __init__(fruit, fruit_name='неизвестный фрукт', weight_kg=None): ... def get_weight_gr(fruit): ...
В методах принято первый аргумент fruit
называть self
. Ход исполнения программы от этого не меняется, но другим программистам будет проще разобраться в коде:
class Fruit(): def __init__(self, fruit_name='неизвестный фрукт', weight_kg=None): self.fruit_name = fruit_name self.weight_kg = weight_kg def get_weight_gr(self): return self. weight_kg * 1000 apple = Fruit('Яблоко', 0.1) orange = Fruit('Апельсин', 0.3) print(apple.fruit_name, "| вес в граммах", apple.get_weight_gr()) print(orange.fruit_name, "| вес в граммах", orange.get_weight_gr())
Когда
__init__
не нуженЧасто новый класс создается не на пустом месте, а наследуется от другого класса, предоставленного библиотекой. Например, так в Django выглядит добавление на сайт нового типа объектов — статей для блога:
from django.db.models import Model class Article(Model): pass
Сразу после объявления нового класса Article
указан класс-предок Model
. Из него будут позаимствованы все методы, включая готовый к использованию __init__
. Теперь внутри класса Article
будет достаточно описать те методы, что отличают его от стандартного класса Model
.
Когда аргументов много
Подобно другим функциям метод может принимать больше одного аргумента. Например:
class Fruit(): . .. def get_title(self, upper_case, max_length): title = self.fruit_name if upper_case: title = title.upper() if max_length: title = title[:max_length] return title
Метод get_title
принимает три аргумента. Так как это не просто функция, а метод, то первым аргументом обязан быть self
. Его значение автоматически подставит Python. Остальные два аргумента upper_case
и max_length
должны быть вручную указаны при вызове метода:
apple.get_title(True, 20)
классов Python
❮ Предыдущая Далее ❯
Классы/объекты Python
Python — это объектно-ориентированный язык программирования.
Почти все в Python является объектом со своими свойствами и методами.
Класс подобен конструктору объектов или «чертежу» для создания объектов.
Создать класс
Чтобы создать класс, используйте ключевое слово class
:
Пример
Создайте класс MyClass со свойством x:
класс MyClass:
x = 5
Попробуйте сами »
Создать объект
Теперь мы можем использовать класс с именем MyClass для создания объектов:
Пример
Создайте объект с именем p1 и выведите значение x:
p1 = MyClass()
print(p1. x)
Попробуйте сами »
Функция __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)
Попробуйте сами »
Примечание: Функция __init__()
вызывается автоматически каждый раз, когда класс используется для создания нового объект.
Методы объекта
Объекты также могут содержать методы. Методы в объектах — это функции, которые принадлежат объекту.
Давайте создадим метод в классе Person:
Пример
Вставьте функцию, которая печатает приветствие, и выполните ее на объекте p1:
class Person:
def __init__(self, name, age):
self.name = имя
self.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 = имя
mysillyobject.age = возраст
def myfunc(abc):
print(«Здравствуйте, меня зовут » + abc.name)
p1 = Person(«Джон»,
36)
p1.myfunc()
Попробуйте сами »
Изменить свойства объекта
Вы можете изменить свойства объектов следующим образом:
Пример
Установите возраст p1 равным 40:
p1.age = 40
Попробуйте сами »
Удалить свойства объекта
Вы можете удалить свойства объектов с помощью del
ключевое слово:
Пример
Удалить свойство age из объекта p1:
del p1. age
Попробуйте сами »
Удалить объекты
Вы можете удалять объекты с помощью del
ключевое слово:
Пример
Удалить объект p1:
del p1
Попробуйте сами »
Оператор pass
класс
, но определения не могут быть пустыми, если определения
у вас по какой-то причине есть определение класса
без содержимого, поместите в оператор pass
, чтобы избежать ошибки.
Пример
класс Человек:
проходит
Попробуйте сами »
Проверьте себя с помощью упражнений
Упражнение:
Создайте класс с именем MyClass:
Мои занятия: х = 5
Начать упражнение
❮ Предыдущий Далее ❯
NEW
Мы только что запустили
Видео W3Schools
Узнать
COLOR PICKER
КОД ИГРЫ
Играть в игру
Top Tutorials
Учебное пособие по HTMLУчебное пособие по CSS
Учебное пособие по JavaScript
Практическое руководство
Учебное пособие по SQL
Учебник по Python
Учебник по W3. CSS
Учебник по Bootstrap
Учебник по PHP
Учебник по Java
Учебник по C++
Учебник по jQuery
Основные ссылки
Справочник по HTMLСправочник по CSS
Справочник по JavaScript
Справочник по SQL
Справочник по Python
Справочник по W3.CSS
Справочник по Bootstrap
Справочник по PHP
Цвета HTML
Справочник по Java
Справочник по Angular
Справочник по jQuery
Top4 Examples Примеры HTML
Примеры CSS
Примеры JavaScript
Примеры инструкций
Примеры SQL
Примеры Python
Примеры W3.CSS
Примеры Bootstrap
Примеры PHP
Примеры Java
Примеры XML
Примеры jQuery
4 FORUM 90 | О
W3Schools оптимизирован для обучения и обучения. Примеры могут быть упрощены для улучшения чтения и обучения. Учебники, ссылки и примеры постоянно пересматриваются, чтобы избежать ошибок, но мы не можем гарантировать полную правильность всего содержания. Используя W3Schools, вы соглашаетесь прочитать и принять наши условия использования, куки-файлы и политика конфиденциальности.
Copyright 1999-2022 Refsnes Data. Все права защищены.
W3Schools работает на основе W3.CSS.
Наследование Python
❮ Предыдущий Далее ❯
Наследование Python
Наследование позволяет нам определить класс, который наследует все методы и свойства другого класса.
Родительский класс — это наследуемый класс, также называемый базовый класс.
Дочерний класс — это класс, который наследуется от другого класса, также называется производным классом.
Создать родительский класс
Любой класс может быть родительским классом, поэтому синтаксис аналогичен созданию любого другой класс:
Пример
Создайте класс с именем Person
, с имя
и фамилия
свойства,
и метод printname
:
class Person:
def __init__(self, fname, lname):
self. firstname = fname
self.lastname = lname
деф имя_печати(я):
print(self.firstname,
self.lastname)
# Используйте класс Person для создания объекта, а затем выполнить метод printname:
x = Person(«John», «Doe»)
x.printname()
Попробуйте сами »
Создать дочерний класс
Чтобы создать класс, который наследует функциональность от другого класс, отправьте родительский класс в качестве параметра при создании дочернего class:
Пример
Создайте класс с именем Студент
, который унаследует свойства
и методы из Person
class:
class Student(Person):
пропуск
Примечание: Используйте пропуск
ключевое слово, если вы не хотите добавлять какие-либо другие свойства или методы в
учебный класс.
Теперь класс Student имеет те же свойства и методы, что и класс Person учебный класс.
Пример
Используйте класс Student
для создания объекта,
а затем выполните printname 9Метод 0018:
x = Student("Mike", "Olsen")
x.printname()
Попробуйте сами »
Добавьте функцию __init__()
До сих пор мы создали дочерний класс, который наследует свойства и методы от его родителя.
Мы хотим добавить функцию __init__()
в дочерний класс (вместо ключевого слова pass
).
Примечание: Функция __init__()
вызывается автоматически каждый раз, когда класс используется для создания нового объекта.
Пример
Добавьте функцию __init__()
в Студент
класс:
класс Студент(Человек):
def __init__(self, fname, lname):
#добавить свойства и т. д.
При добавлении функции __init__()
дочерний класс больше не будет наследовать
родительская функция __init__()
.
Примечание: Дочерний __init__()
функция переопределяет наследование родителя __init__()
функция.
Чтобы сохранить наследство родителя __init__()
функцию, добавьте вызов в
родительская функция __init__()
:
Пример
class Student(Person):
def __init__(self, fname, lname):
Person.__init__(self, fname, lname)
Попробуйте сами »
Теперь мы успешно добавили функцию __init__() и сохранили
наследование родительского класса, и мы готовы добавить функциональность в __init__()
функция.
Используйте функцию super()
Python также имеет функцию super()
, которая
заставит дочерний класс наследовать все методы и свойства от его
parent:
Пример
class Student(Person):
def __init__(self, fname, lname):
super().__init__(fname, lname)
Попробуйте сами »
Используя функцию super()
, вы не
должны использовать имя родительского элемента, он автоматически унаследует
методы и свойства от своего родителя.
Добавить свойства
Пример
Добавьте свойство с именем выпускной год
в Студент
класс:
класс Студент(Человек):
def __init__(self, fname, lname):
super().__init__(fname, lname)
self.graduationyear
= 2019
Попробуйте сами »
В приведенном ниже примере год 2019
должен быть переменной и передаваться в Класс Student
при создании объектов Student.
Для этого добавьте еще один параметр в функцию __init__():
Пример
Добавьте параметр года
и передайте правильный
год создания объектов:
class Student(Person):
def __init__(self, fname, lname, year):
super().__init__(fname, lname)
self.graduationyear
= год
x = студент («Майк», «Олсен», 2019)
Попробуйте сами »
Добавить методы
Пример
Добавьте метод с именем welcome
в Студент
класс:
class Student(Person):
def __init__(self, fname, lname, year):
super(). __init__(fname, lname)
self.graduationyear
= год
def welcome(self):
print("Добро пожаловать",
self.firstname, self.lastname, «в класс», self.graduationyear)
Попробуйте сами »
Если вы добавите в дочерний класс метод с тем же именем, что и функция в родительского класса, наследование родительского метода будет переопределено.
Проверьте себя с помощью упражнений
Упражнение:
Каков правильный синтаксис для создания класса Student, который будет наследовать свойства и методы класса Person?
учебный класс :
Начать упражнение
❮ Предыдущий Далее ❯
Классы и объекты Python — GeeksforGeeks
Класс — это определяемый пользователем план или прототип, на основе которого создаются объекты. Классы предоставляют средства объединения данных и функций. Создание нового класса создает новый тип объекта, позволяя создавать новые экземпляры этого типа. К каждому экземпляру класса могут быть прикреплены атрибуты для поддержания его состояния. Экземпляры класса также могут иметь методы (определяемые их классом) для изменения их состояния.
Чтобы понять необходимость создания класса в Python, давайте рассмотрим пример. Допустим, вы хотите отслеживать количество собак, которые могут иметь разные атрибуты, такие как порода и возраст. Если используется список, первым элементом может быть порода собаки, а вторым элементом может быть ее возраст. Предположим, есть 100 разных собак, тогда как узнать, какой элемент должен быть каким? Что, если бы вы захотели добавить этим собакам другие свойства? Этому не хватает организации, и это именно то, что нужно для занятий.
Синтаксис: Определение класса
class ClassName: # Заявление
Синтаксис: Определение объекта
obj = ClassName() print(obj.atrr)
Класс создает определяемую пользователем структуру данных, которая содержит свои собственные элементы данных и функции-члены, доступ к которым и их использование можно получить, создав экземпляр этого класса. Класс подобен чертежу объекта.
Некоторые моменты в классе Python:
- Классы создаются по ключевому слову class.
- Атрибуты — это переменные, принадлежащие классу.
- Атрибуты всегда общедоступны, и к ним можно получить доступ с помощью оператора точка (.). Например: Myclass.Myattribute
# Программа Python3 для # продемонстрировать определение # класс класс Собака: pass
В приведенном выше примере ключевое слово class указывает, что вы создаете класс, за которым следует имя класса (в данном случае Dog).
Объекты класса
Объект является экземпляром класса. Класс похож на чертеж, а экземпляр — это копия класса с 90 577 фактическими значениями 90 578 . Это уже не идея, это настоящая собака, как собака породы мопс, которой семь лет. У вас может быть много собак для создания множества разных экземпляров, но без класса в качестве руководства вы бы потерялись, не зная, какая информация требуется.
Объект состоит из:
- Состояние: Он представлен атрибутами объекта. Он также отражает свойства объекта.
- Поведение: Представлено методами объекта. Он также отражает реакцию объекта на другие объекты.
- Идентификация: Дает уникальное имя объекту и позволяет одному объекту взаимодействовать с другими объектами.
Объявление объектов (также называемое созданием экземпляра класса)
Когда создается объект класса, говорят, что экземпляр класса создается. Все экземпляры имеют общие атрибуты и поведение класса. Но значения этих атрибутов, то есть состояние, уникальны для каждого объекта. Один класс может иметь любое количество экземпляров.
Example:
Declaring an objectPython3
3 9
|
Выход
333
20993339000 3
209.
3399073
. я млекопитающее я собакаВ приведенном выше примере создается объект, который в основном представляет собой собаку по имени Роджер. Этот класс имеет только два атрибута класса, которые говорят нам, что Роджер — собака и млекопитающее.
Методы класса self
- должны иметь дополнительный первый параметр в определении метода. Мы не даем значение этому параметру при вызове метода, его предоставляет Python.
- Если у нас есть метод, который не принимает аргументов, у нас все еще есть один аргумент.
- Это похоже на этот указатель в C++ и эту ссылку в Java.
Когда мы вызываем метод этого объекта как myobject.method(arg1, arg2), он автоматически преобразуется Python в MyClass.method(myobject, arg1, arg2) — это все, что касается особого self.
Метод __init__
Метод __init__ аналогичен конструкторам в C++ и Java. Конструкторы используются для инициализации состояния объекта. Как и методы, конструктор также содержит набор операторов (т. е. инструкций), которые выполняются во время создания объекта. Он запускается, как только создается экземпляр объекта класса. Этот метод полезен для любой инициализации, которую вы хотите выполнить с вашим объектом.
Python3
class
Person:
def
__init__(
self
, name):
self
.name
=
Имя
DEF
SAY_HI (
SEUL
SAY_HI (
SEUL
0017):
9002
Печать
(
'Здравствуйте, мое имя -
,
Self
. NAME)
.
'nikhil'
)
P.Say_HI ()
Выход:
Hello, My Anty Armanly 105. для каждого экземпляра, а переменные класса предназначены для атрибутов и методов, общих для всех экземпляров класса. Переменные экземпляра — это переменные, значение которых присваивается внутри конструктора или метода с self, тогда как переменные класса — это переменные, значение которых присваивается в классе.
Определение переменных экземпляра с помощью конструктора.
Python3
class
Dog:
animal
=
'dog'
def
__init__(
self
, порода, окрас):
self
. breed
=
breed
self
.color
=
color
Rodger
=
Собака(
"Мопс"
,
"коричневый"
)
Бузо
=
.80018
"Bulldog"
,
"black"
)
(
'Rodger details:'
)
(
'Rodger is a
, Rodger.Animal)
Печать
(
'Порода:'
, Rodger.freed)
(
'.
Печать
(
'\ nbuzo Подробности:'
)
Печать
(
'Buzo -
, BUZO)
'Порода:'
, Buzo.breed)
Печать
(
'Цвет:'
, Buzo.color)
. используя имя класса"
)
печать
(Собака.животное)
Выход
Детали Роджера: Роджер - собака Порода: Мопс Коричневый цвет Детали Бузо: Бузо - собака Порода: Бульдог Черный цвет Доступ к переменной класса по имени класса собакаОпределение переменных экземпляра с использованием обычного метода.
Python3
класс
Dog:
animal
=
'dog'
def
__init__(
self
, breed) :
Self
. Breed
=
порода
=
порода
.0027
def
setColor(
self
, color):
self
. color
=
color
def
getColor(
self
):
return
self
3
1 .color
0002
Rodger
=
Dog(
"pug"
)
Rodger.setColor(
"brown"
)
(Rodger.getColor( ))
Выход
коричневыйКлассы и объекты Python [с примерами]
В этом руководстве вы узнаете об основных функциях объектов и классов Python. Вы узнаете, что такое класс, как его создать и использовать в своей программе.
Объекты и классы Python
Python — это объектно-ориентированный язык программирования. В отличие от процедурно-ориентированного программирования, где основное внимание уделяется функциям, объектно-ориентированное программирование делает упор на объекты.
Объект — это просто набор данных (переменных) и методов (функций), которые воздействуют на эти данные. Точно так же класс является планом для этого объекта.
Мы можем думать о классе как о эскизе (прототипе) дома. В нем указаны все подробности об этажах, дверях, окнах и т. д. На основе этих описаний мы строим дом. Дом – это объект.
Так же, как многие дома можно построить по чертежу дома, мы можем создать много объектов из класса. Объект также называется экземпляром класса, а процесс создания этого объекта называется созданием экземпляра .
Определение класса в Python
Подобно тому, как определения функций начинаются с ключевого слова def в Python, определения классов начинаются с ключевого слова class.
Первая строка внутри класса называется docstring и содержит краткое описание класса. Хотя это и не обязательно, это настоятельно рекомендуется.
Вот простое определение класса.
класс MyNewClass: '''Это строка документации. Я создал новый класс ''' passКласс создает новое локальное пространство имен, в котором определены все его атрибуты. Атрибуты могут быть данными или функциями.
В нем также есть специальные атрибуты, начинающиеся с двойного подчеркивания
__
. Например,__doc__
дает нам строку документации этого класса.Как только мы определяем класс, создается новый объект класса с тем же именем. Этот объект класса позволяет нам получить доступ к различным атрибутам, а также создавать экземпляры новых объектов этого класса.
класс Лицо: «Это класс людей» возраст = 10 приветствие (себя): распечатать('Здравствуйте') # Выход: 10 печать(лицо.возраст) # Вывод: <функция Person. greet> печать (человек.приветствовать) # Вывод: "Это класс человека" print(Person.__doc__)Вывод
10 <функция Person.greet по адресу 0x7fc78c6e8160> Это класс человекаСоздание объекта в Python
Мы видели, что объект класса можно использовать для доступа к различным атрибутам.
Его также можно использовать для создания новых экземпляров объектов (экземпляров) этого класса. Процедура создания объекта аналогична вызову функции.
>>> harry = Person()Это создаст новый экземпляр объекта с именем harry . Мы можем получить доступ к атрибутам объектов, используя префикс имени объекта.
Атрибуты могут быть данными или методом. Методы объекта являются соответствующими функциями этого класса.
Это значит, что с
Person.greet
— объект функции (атрибут класса),Person.greet
— объект метода.класс Лицо: «Это класс людей» возраст = 10 приветствие (себя): распечатать('Здравствуйте') # создаем новый объект класса Person Гарри = Человек() # Вывод: <функция Person. greet> печать (человек.приветствовать) # Вывод: <связанный метод Person.greet объекта <__main__.Person>> распечатать (приветствовать Гарри) # Вызов метода приветствия() объекта # Вывод: привет harry.greet ()Выход
<функция Person.greet по адресу 0x7fd288e4e160> <связанный метод Person.greet объекта <__main__.Person по адресу 0x7fd288e9fa30>> HelloВозможно, вы заметили параметр
self
в определении функции внутри класса, но мы вызвали метод просто какharry.greet()
без каких-либо аргументов. Это все еще работало.Это связано с тем, что всякий раз, когда объект вызывает свой метод, сам объект передается в качестве первого аргумента. Итак,
harry.greet()
переводится какPerson.greet(harry)
.В целом, вызов метода со списком из n аргументов эквивалентен вызову соответствующей функции со списком аргументов, который создается путем вставки объекта метода перед первым аргументом.
По этим причинам первым аргументом функции в классе должен быть сам объект. Это условно называется self . Его можно назвать иначе, но мы настоятельно рекомендуем следовать условности.
Теперь вы должны быть знакомы с объектом класса, объектом экземпляра, объектом функции, объектом метода и их различиями.
Конструкторы в Python
Функции класса, начинающиеся с двойного подчеркивания
__
, называются специальными функциями, поскольку они имеют особое значение.Особый интерес представляет функция
__init__()
. Эта специальная функция вызывается всякий раз, когда создается экземпляр нового объекта этого класса.Этот тип функций также называется конструкторами в объектно-ориентированном программировании (ООП). Обычно мы используем его для инициализации всех переменных.
класс Комплексный номер: def __init__(я, r=0, i=0): селф.реал = р селф.имаг = я защита get_data (я): print(f'{self. real}+{self.imag}j') # Создаем новый объект ComplexNumber num1 = комплексное число (2, 3) # Вызов метода get_data() # Вывод: 2+3j число1.get_data() # Создать еще один объект ComplexNumber # и создайте новый атрибут 'attr' num2 = комплексное число (5) число2.атрибут = 10 # Вывод: (5, 0, 10) print((num2.real, num2.imag, num2.attr)) # но объект c1 не имеет атрибута 'attr' # AttributeError: объект 'ComplexNumber' не имеет атрибута 'attr' печать (num1.attr)Выход
2+3к (5, 0, 10) Traceback (последний последний вызов): Файл "", строка 27, в печать (num1.attr) AttributeError: объект «ComplexNumber» не имеет атрибута «attr» В приведенном выше примере мы определили новый класс для представления комплексных чисел. Он имеет две функции:
__init__()
для инициализации переменных (по умолчанию 0) иget_data()
для правильного отображения числа.Интересно отметить, что на предыдущем шаге атрибуты объекта можно создавать на лету. Мы создали новый атрибут attr для объекта num2 и прочитать его. Но это не создает этот атрибут для объекта num1 .
Удаление атрибутов и объектов
Любой атрибут объекта может быть удален в любое время с помощью оператора
del
. Попробуйте следующее в оболочке Python, чтобы увидеть результат.>>> num1 = КомплексноеЧисло(2,3) >>> дел num1.imag >>> num1.get_data() Traceback (последний последний вызов): ... AttributeError: объект «ComplexNumber» не имеет атрибута «imag» >>> del ComplexNumber.get_data >>> num1.get_data() Traceback (последний последний вызов): ... AttributeError: объект «ComplexNumber» не имеет атрибута «get_data»Мы можем даже удалить сам объект, используя оператор del.
>>> c1 = комплексное число (1,3) >>> дель c1 >>> с1 Traceback (последний последний вызов): ... NameError: имя 'c1' не определеноНа самом деле все сложнее. Когда мы делаем
c1 = ComplexNumber(1,3)
, в памяти создается новый экземпляр объекта, и с ним связывается имя c1 .По команде
del c1
эта привязка удаляется и имя c1 удаляется из соответствующего пространства имен. Однако объект продолжает существовать в памяти, и если с ним не связано другое имя, он позже автоматически уничтожается.Это автоматическое уничтожение объектов, на которые нет ссылок, в Python также называется сборкой мусора.
Удаление объектов в Python удаляет привязку имениОпределить классы в Python
Python — полностью объектно-ориентированный язык. Вы работали с классами и объектами с самого начала этих руководств. Каждый элемент программы на Python является объектом класса. Число, строка, список, словарь и т. д., используемые в программе, являются объектами соответствующего встроенного класса. Вы можете получить имя класса переменных или объектов, используя метод type(), как показано ниже.
>>> число=20 >>> тип(число) <класс 'целое число'> >>> с="Питон" >>> тип(ы) <класс 'ул'>Определение класса
Класс в Python можно определить с помощью ключевого слова
class
.класс <имя_класса>: <оператор1> <оператор2> . . <инструкцияN>В соответствии с приведенным выше синтаксисом класс определяется с помощью ключевого слова
class
, за которым следует имя класса, и оператора:
после имени класса, что позволяет продолжить определение членов класса на следующей строке с отступом. Следующие являются членами класса.
- Атрибуты класса
- Конструктор
- Атрибуты экземпляра
- Характеристики
- Методы класса
Класс также может быть определен без каких-либо членов. В следующем примере определяется пустой класс с использованием ключевого слова
Ученикpass
.класса: проходитьПри создании экземпляра класса используется функциональная нотация. Чтобы создать объект класса, просто вызовите класс как функцию без параметров, которая возвращает новый объект класса, как показано ниже.
станд = студент ()Выше,
Student()
возвращает объект классаStudent
, который присваивается локальной переменнойstd
. КлассStudent
является пустым классом, поскольку он не содержит членов.Атрибуты класса
Атрибуты класса — это переменные, определенные непосредственно в классе, которые являются общими для всех объектов класса. Доступ к атрибутам класса можно получить, используя имя класса, а также используя объекты.
Учениккласса: schoolName = 'Школа XYZ'Выше
schoolName
— это атрибут класса, определенный внутри класса. ЗначениеschoolName
останется одинаковым для всех объектов, если не будет изменено явно.>>> Student.schoolName "Школа XYZ" >>> стд = Студент() >>> std.schoolName "Школа XYZ"Как видите, доступ к атрибуту класса осуществляется с помощью
Student.schoolName
, а такжеstd.schoolName
. Изменение значения атрибута класса с использованием имени класса изменит его во всех экземплярах. Однако изменение значения атрибута класса с использованием экземпляра не отразится на других экземплярах или классе.>>> Student.schoolName = 'ABC School' # изменить значение атрибута, используя имя класса >>> стд = Студент() >>> std.schoolName 'ABC School' # значение изменено для всех экземпляров >>> std.schoolName = 'My School' # изменение атрибута экземпляра >>> std.schoolName 'Моя школа' >>> Student.schoolName # изменение уровня экземпляра не отразилось на атрибуте класса «Школа азбуки» >>> std2 = Студент() >>> std2. schoolName «Школа азбуки»В следующем примере показано использование атрибута класса
Ученикcount
.класса: количество = 0 защита __init__(сам): Количество студентов += 1В приведенном выше примере
count
является атрибутом класса Student. Всякий раз, когда создается новый объект, значениеcount
увеличивается на 1. Теперь вы можете получить доступ к атрибутуcount
после создания объектов, как показано ниже.>>> std1=Студент() >>> Количество студентов 1 >>> std2 = Студент() >>> Количество студентов 2Конструктор
В Python метод конструктора вызывается автоматически всякий раз, когда создается экземпляр нового объекта класса, так же, как конструкторы в C# или Java. Конструктор должен иметь специальное имя
__init__()
и специальный параметр с именемself
.Первым параметром каждого метода в классе должен быть
self
, который ссылается на вызывающий объект. Однако вы можете дать любое имя первому параметру, не обязательноself
.В следующем примере определяется конструктор.
Учениккласса: def __init__(self): # метод конструктора print('Вызван конструктор')Теперь всякий раз, когда вы создаете объект класса
Student
, будет вызываться метод конструктора__init__()
, как показано ниже.>>>s1 = Студент() Вызван конструктор >>>s2 = Студент() Вызван конструкторКонструктор в Python используется для определения атрибутов экземпляра и присвоения им значений.
Атрибуты экземпляра
Атрибуты экземпляра — это атрибуты или свойства, прикрепленные к экземпляру класса. Атрибуты экземпляра определяются в конструкторе.
В следующем примере определяются атрибуты экземпляра
Ученикимя
ивозраст
в конструкторе.класса: schoolName = 'XYZ School' # атрибут класса def __init__(self): # конструктор self.name = '' # атрибут экземпляра self.age = 0 # атрибут экземпляраДоступ к атрибуту экземпляра можно получить с помощью записи через точку:
[имя экземпляра].[имя атрибута]
, как показано ниже.>>> стд = Студент() >>> стандартное имя '' >>> стд.возраст 0Вы можете установить значение атрибутов с помощью записи через точку, как показано ниже.
>>> стд = Студент() >>> std.name = "Bill" # присвоить значение атрибуту экземпляра >>> std.age=25 # присвоить значение атрибуту экземпляра >>> std.name # доступ к значению атрибута экземпляра Билл >>> std.age # значение доступа к атрибуту экземпляра 25Вы можете указать значения атрибутов экземпляра через конструктор. Следующий конструктор включает параметры имени и возраста, кроме параметра
Ученикself
.класса: def __init__(я, имя, возраст): self.name = имя возраст = возрастТеперь вы можете указать значения при создании экземпляра, как показано ниже.
>>> std = Студент('Билл',25) >>> стандартное имя 'Билл' >>> стд.возраст 25Вам не нужно указывать значение параметра
self
. Он будет назначен внутри Python.Вы также можете установить значения по умолчанию для атрибутов экземпляра. Следующий код устанавливает значения по умолчанию для параметров конструктора. Таким образом, если значения не указаны при создании объекта, значения будут присвоены позже.
Учениккласса: def __init__(я, имя = "Гость", возраст = 25) self.name=имя self.age=возрастТеперь вы можете создать объект со значениями по умолчанию, как показано ниже.
>>> стд = Студент() >>> стандартное имя «Гость» >>> стд.возраст 25Посетите атрибуты класса и атрибуты экземпляра в Python для получения дополнительной информации.
Свойства класса
В Python свойство в классе может быть определено с помощью функции property().
Метод
property()
в Python предоставляет интерфейс к атрибутам экземпляра. Он инкапсулирует атрибуты экземпляра и предоставляет свойство, такое же, как в Java и C#.Метод
property()
принимает методы get, set и delete в качестве аргументов и возвращает объект изсвойство
класс.В следующем примере показано, как создать свойство в Python с помощью функции
Ученикproperty()
.класса: защита __init__(сам): сам.__имя='' def setname(я, имя): print('вызвано setname()') self.__name=имя определение имя(я): print('вызвано getname()') вернуть себя.__имя имя = свойство (getname, setname)В приведенном выше примере
property(getname, setname)
возвращает объект свойства и присваивает емуname
. Таким образом, свойствоname
скрывает атрибут частного экземпляра__name
. Доступ к свойствуname
осуществляется напрямую, но внутри оно вызовет методgetname()
илиsetname()
, как показано ниже.>>> стд = Студент() >>> std.name="Стив" setname() вызывается >>> стандартное имя getname() вызывается 'Стив'Рекомендуется использовать декоратор свойств вместо метода
property()
.Методы класса
Вы можете определить столько методов, сколько хотите в классе, используя ключевое слово
Ученикdef
. Каждый метод должен иметь первый параметр, обычно называемыйself
, который относится к вызывающему экземпляру.класса: def displayInfo(self): # метод класса print('Информация о студенте')
Self
— это просто условное имя для первого аргумента метода в классе. Метод, определенный какmymethod(self, a, b)
, должен вызываться какx.mymethod(a, b)
для объекта классаx
.Приведенный выше метод класса можно вызывать как обычную функцию, как показано ниже.
>>> стд = Студент() >>> std.displayInfo() «Информация для студентов»Первый параметр метода может не называться
Ученикself
. Вы можете указать любое имя, относящееся к экземпляру вызывающего метода. Следующий методdisplayInfo()
называет первый параметр какobj
вместоself
, и это прекрасно работает.класса: def displayInfo(obj): # метод класса print('Информация о студенте')Определение метода в классе без параметра
Ученикself
вызовет исключение при вызове метода.класса: def displayInfo(): # метод без собственного параметра print('Информация о студенте')>>> стд = Студент() >>> std. displayInfo() Traceback (последний последний вызов): std.displayInfo() TypeError: displayInfo() принимает 0 позиционных аргументов, но был задан 1Метод может получить доступ к атрибутам экземпляра, используя параметр
Ученикself
.класса: def __init__(я, имя, возраст): self.name = имя возраст = возраст def displayInfo(self): # метод класса print('Имя ученика: ', self.name,', Возраст: ', self.age)Теперь вы можете вызвать метод, как показано ниже.
>>> std = Студент('Стив', 25) >>> std.displayInfo() Имя ученика: Стив, Возраст: 25Удаление атрибута, объекта, класса
Вы можете удалить атрибуты, объекты или сам класс, используя ключевое слово
del
, как показано ниже.>>> std = Студент('Стив', 25) >>> del std. name # удаление атрибута >>> стандартное имя Traceback (последний последний вызов): Файл "", строка 1, в стандартное имя AttributeError: объект «Студент» не имеет атрибута «имя» >>> del std # удаление объекта >>> стандартное имя Traceback (последний последний вызов): Файл " ", строка 1, в стандартное имя NameError: имя 'std' не определено >>> del Student # удаление класса >>> std = Студент('Стив', 25) Traceback (последний последний вызов): Файл " ", строка 1, в станд = студент () NameError: имя «Студент» не определено Классы и объекты Python — блог Intellipaat
Python — это объектно-ориентированный язык, и почти каждая сущность в Python является объектом, а это означает, что программисты широко используют классы и объекты при написании кода на Python. Объекты в Python — это, по сути, инкапсуляция переменных и функций Python, которые они получают из классов.
В этом модуле мы изучим каждый аспект классов и объектов в Python в следующем порядке:
- Что такое объект в Python?
- Концепция класса Python
- Пример классов и объектов Python
- Преимущества использования классов в Python
- Создание класса Python
- Создание объекта в Python
- типов классов в Python
- Абстрактный класс Python
- Бетон Python Класс
- Частичный класс Python
- Функция __init__() в Python
- Наследование Python и его типы
- Полиморфизм Python
- Изменяемые и неизменяемые объекты в Python
Итак, без дальнейших проволочек, приступим.
Посмотрите это видео на «классах и объектах Python»:Классы Python и объекты Python Class and Objects
Go Apport Professional Python Course Online In Online In Toronto 2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 2 . в настоящее время!
Что такое объект в Python?Python — это язык программирования, ориентированный на объектно-ориентированное программирование. В Python почти все является объектом. Мы можем проверить, является ли питон объектом, используя метод type(). Это просто набор переменных и функций Python. В Python существуют различные типы объектов, такие как списки, словари, файлы, наборы, строки и т. д. Объект определяется своим классом. Например, целочисленная переменная является членом целочисленного класса. Объект является физическим объектом. Свойства объекта следующие. Состояние, идентичность и поведение — это три ключевых свойства объекта.
Концепция класса PythonОпределение класса Python — это просто логическая сущность, которая ведет себя как прототип или шаблон для создания объектов. Классы Python предоставляют методы, которые можно использовать для изменения состояния объекта. Они также определяют качества, которыми может обладать объект.
Переменные класса Python
Все экземпляры объекта класса совместно используют переменную класса Python. При создании класса определяются переменные. Они не определены ни в одном из методов класса.
Переменные и функции определяются внутри класса, и доступ к ним осуществляется с помощью объектов. Эти переменные и функции вместе известны как атрибуты.
Пример классов и объектов PythonДавайте рассмотрим пример, чтобы понять концепцию классов и объектов Python. Мы можем думать об объекте как об обычном повседневном объекте, скажем, о машине. Теперь, как обсуждалось выше, мы знаем, что класс имеет данные и функции, определенные внутри него, и все эти данные и функции можно рассматривать как свойства и действия объекта соответственно. То есть характеристики (данные) автомобиля (объекта) — это цвет, цена, количество дверей и т. д. Действия (функции) автомобиля (объекта) — скорость, применение тормозов и т. д. Несколько объектов с разными данными и связанные с ними функции могут быть созданы с использованием класса, как показано на следующей диаграмме.
Преимущества использования классов в Python
- Классы обеспечивают простой способ хранения элементов данных и методов вместе в одном месте, что помогает сделать программу более организованной.
- Использование классов также предоставляет другую функциональность этой парадигмы объектно-ориентированного программирования, а именно наследование. Классы
- также помогают переопределить любой стандартный оператор.
- Использование классов позволяет повторно использовать код, что делает программу более эффективной.
- Группировка связанных функций и хранение их в одном месте (внутри класса) обеспечивает чистую структуру кода, что повышает удобочитаемость программы.
Станьте профессиональным программистом на Python с этим полным курсом обучения Python в Сингапуре !
Создание класса PythonТочно так же, как функция в Python определяется с помощью ключевого слова def, класс в Python также определяется с помощью ключевого слова class, за которым следует имя класса.
Подобно функциям, мы также используем строки документации в классах. Хотя использование строк документации не является обязательным, все же рекомендуется, поскольку считается хорошей практикой включать краткое описание класса для повышения удобочитаемости и понятности кода.
В следующем примере показано, как определить класс в Python:
class IntellipaatClass: «Здесь операторы и методы класса»
Оператор create class создаст локальное пространство имен для всех атрибутов, включая специальные атрибуты, начинающиеся с двойного подчеркивания (__), например, __init__() и __doc__(). Как только класс создан, также создается объект класса, который используется для доступа к атрибутам в классе, давайте разберемся в этом с помощью примера класса Python.
класс IntellipaatClass: а = 5 деф функция1(я): print('Добро пожаловать в Intellipaat') #доступ к атрибутам с помощью одноименного объекта класса IntellipaatClass.function(1) печать (IntellipaatClass.a)
Вывод:
Добро пожаловать в Intellipaat 5Создание объекта в Python
В предыдущем разделе мы видели, что объект класса с тем же именем, что и у класса, используется для доступа к атрибутам. Это не все, для чего используется объект класса; его также можно использовать для создания новых объектов, а затем эти объекты можно использовать для доступа к атрибутам, как показано в следующем примере:
класс IntellipaatClass: а = 5 деф функция1(я): print('Добро пожаловать в Intellipaat')#создание нового объекта с именем object1 с использованием класса object объект1 = IntellipaatClass ()
Вывод:
Добро пожаловать в Intellipaat
Мы должны заметить, что мы используем параметр с именем self при определении функции в классе, но на самом деле мы не передаем никакого значения при вызове функции. Это связано с тем, что когда функция вызывается с использованием объекта, сам объект автоматически передается функции в качестве аргумента, поэтому object1.function1() эквивалентен object1.function1(object1). Поэтому самым первым аргументом в функции должен быть сам объект, который условно называется «я». Его также можно назвать как-то иначе, но называть его «я» — это соглашение, и считается хорошей практикой следовать этому соглашению.
Изменение и удаление объекта
Вы можете изменить объект следующим образом:
Person.age=20
Вы можете удалить объект, используя ключевое слово del
Например,
del имя_объекта
Примите участие в этом углубленном курсе Python Training in Hyderabad прямо сейчас!
Типы классов в PythonВ Python существуют различные типы классов, некоторые из которых следующие:
- Абстрактный класс Python
- Python Бетон класса
- Частичный класс Python
Давайте углубимся в детали, чтобы лучше понять.
Абстрактный класс PythonАбстрактный класс — это класс, содержащий один или несколько абстрактных методов. Термин «абстрактный метод» относится к методу, у которого есть объявление, но нет реализации. При работе с большой кодовой базой может быть сложно запомнить все классы. Именно тогда можно использовать абстрактный класс Python. Python, в отличие от большинства языков высокого уровня, по умолчанию не имеет абстрактного класса.
Класс можно определить как абстрактный класс с помощью abc.ABC, а метод можно определить как абстрактный метод с помощью abc.abstractmethod. Аббревиатура абстрактного базового класса — ABC. Модуль ABC, обеспечивающий основу для создания абстрактных базовых классов, должен быть импортирован. Модуль ABC работает, оформляя методы базового класса как абстрактные. Он устанавливает конкретные классы как реализации абстрактной базы.
Пример:
From abc import ABC, abstractmethod Класс АбстрактноеИмяКласса(ABC): @абстрактный метод def abstract_method_name (я): ПроходитьКонкретный класс Python
Конкретные классы имеют только конкретные методы, но абстрактные классы могут иметь как конкретные, так и абстрактные методы. Конкретный класс реализует абстрактные методы, но абстрактный базовый класс также может делать это, инициируя методы через super().
Частичный класс PythonЧастичный класс — это один из классов Python. Мы можем использовать его для разработки новой функции, которая применяет только подмножество операторов и ключевых слов, которые вы ей передаете. Вы можете использовать partial, чтобы заморозить часть операторов и/или ключевых слов вашей функции, что приведет к созданию нового объекта. Мы можем использовать модуль Functools для реализации этого класса.
Получите 100%-й подъем!
Овладейте самыми востребованными навыками прямо сейчас!
Файловый объект PythonФайловый объект Python обеспечивает доступ к файлам и управление ими с помощью методов и свойств. Мы можем читать и записывать любой файл, используя файловые объекты.
Python создает файловый объект всякий раз, когда мы открываем файл для выполнения над ним каких-либо операций. Мы можем использовать встроенные функции Python, такие как open() и os.popen, для создания файлового объекта ().
При неправильном использовании файлового объекта или сбое действия с файлом из-за проблемы, связанной с вводом-выводом, создается исключение IOError.
Файловый объект можно разделить на три категории: текстовые файлы, двоичные файлы и необработанные файлы.
Функция The_init_() в PythonВ классах Python метод «__init__» зарезервирован. Он автоматически вызывается при создании объекта с использованием класса и используется для инициализации переменных класса. Он эквивалентен конструктору.
- Как и любой другой метод, метод init начинается с ключевого слова «def»
- «self» является первым параметром в этом методе, как и в любом другом методе, хотя в случае init «self» относится к вновь созданному объекту, в отличие от других методов, где он относится к текущему объекту или экземпляру, связанному с этим конкретным методом.
- Можно добавить дополнительные параметры
В следующем примере показано, как использовать функцию __init__():
class IntellipaatClass: def __init__(я, курс): самостоятельный курс = курс дисплей защиты (я): распечатать(самостоятельно. курс) объект1 = IntellipaatClass("Python") объект1.дисплей() Выход: питон
В приведенном выше примере функция инициализации ведет себя как конструктор и вызывается автоматически, как только выполняется оператор «object1 = IntellipaatClass(«Python»)». Поскольку это функция внутри класса, первый аргумент, переданный в нее, — это сам объект, который перехватывается в параметре «я». Второй параметр, т. е. курс, используется для перехвата второго аргумента, передаваемого через объект, то есть «Python». И затем мы инициализировали переменную курса внутри функции инициализации. Кроме того, мы определили еще одну функцию с именем display для вывода значения переменной. Эта функция вызывается с помощью object1.
Примечание. Не забудьте указать правильный отступ в приведенном выше коде.
Наследование Python и его типыБудучи объектно-ориентированным языком программирования, Python также использует наследование. Способность класса наследовать свойства другого класса называется наследованием. Класс, который наследует свойства, обычно называют подклассом или производным классом. И наследуемый класс известен как суперкласс или базовый класс.
Наследование обеспечивает возможность повторного использования кода, поскольку мы можем использовать существующий класс и его свойства, а не создавать класс с нуля с теми же свойствами.
класс производное_имя_класса (базовый класс):
Пример:
класс Intellipaat: курс по определению (сам): print("Учебник по Python") привет класс (Intellipaat): функция защиты (сам): print("Добро пожаловать в Intellipaat") ob1 = привет () ob1.func() ob1.курс()
Вывод:
Добро пожаловать в Intellipaat Учебник по Python
Существуют различные формы наследования в зависимости от структуры наследования между производным классом и базовым классом в Python. Давайте обсудим каждый из них в отдельности:
- Одиночное наследование: Тип наследования, когда класс наследует только один базовый класс, известен как одиночное наследование, как мы видели в приведенном выше примере.
- Множественное наследование: Когда класс наследует несколько базовых классов, это называется множественным наследованием. В отличие от таких языков, как Java, Python полностью поддерживает множественное наследование. Все базовые классы указаны внутри скобок в виде списка, разделенного запятыми.
Пример:
класс BaseClass1(): защита __init__(сам): print("Базовый класс 1") класс БазовыйКласс2(): защита __init__(сам): print("Базовый класс 2") производный класс класса (BaseClass1, BaseClass2): защита __init__(сам): BaseClass1.__init__(сам) BaseClass2.__init__(сам) print("производный класс") определение display_all (я): печать (я.об1, я.об2) об = производный класс ()
Выход:
Базовый класс 1 Базовый класс 2 производный класс
- Многоуровневое наследование: Когда класс наследует базовый класс, а затем другой класс наследует этот ранее производный класс, образуя структуру класса «родительский, дочерний и внучатый», это называется многоуровневым наследованием.
класс BaseClass(): защита __init__(сам): print("Базовый класс") класс дочерний класс (базовый класс): защита __init__(сам): print("Дочерний класс") класс grandchildClass (childClass): защита __init__(сам): Базовый класс.__init__(сам) childClass.__init__(я) print("Великий дочерний класс") ob1 = внуккласс()
Выход:
Базовый класс Дочерний класс Большой детский класс
- Иерархическое наследование: Когда существует только один базовый класс, наследуемый несколькими производными классами, это называется иерархическим наследованием.
- Гибридное наследование: Гибридное наследование — это сочетание вышеупомянутых типов наследования, то есть сочетание нескольких типов наследования.
У нас есть идеальный профессионал Курс Python в Бангалоре для вас!
Карьерный переход
Частные атрибуты класса в PythonПри реализации наследования существуют определенные случаи, когда мы не хотим, чтобы все атрибуты класса были унаследованы производным классом. В таких случаях мы можем сделать эти атрибуты закрытыми членами базового класса. Мы можем просто сделать это, добавив два символа подчеркивания (__) перед именем переменной.
Пример:
класс Base1: защита __init__(сам): я.х = 10 # создание приватной переменной с именем y защита __init__(сам): я.__у = 5 класс Derived1 (Base1): защита __init__(сам): я.г = 20 Base1.__init__(сам) ob1 = Производный1() печать(ob1.y)
При выполнении приведенного выше блока кода выдается следующая ошибка:
Вывод:
Трассировка (последний последний вызов): Файл «», строка 1, в AttributeError: объект «Derived1» не имеет атрибута «y»
Поскольку y является закрытой переменной в базовом классе, производный класс не может получить к ней доступ.
Полиморфизм в PythonПолиморфизм означает наличие множества форм. Полиморфизм позволяет использовать один интерфейс с разными типами данных Python , разными классами или даже с разным количеством входных данных.
Полиморфизм бывает двух типов:
- Полиморфизм времени выполнения
- Полиморфизм времени компиляции
Полиморфизм времени выполнения — это процесс, в котором вызов переопределенного метода разрешается во время выполнения. В Python мы реализуем полиморфизм во время выполнения посредством переопределения методов.
Переопределение метода позволяет изменить реализацию метода в дочернем классе, который определен в родительском классе.
Чтобы переопределить метод, должны быть выполнены следующие условия:
- Должно быть наследование. Дочерний класс должен быть производным от родительского класса.
- Метод, который мы переопределяем, должен иметь то же количество параметров, что и метод в родительском классе.
Пример:
класс Животные: звук определения (я): print("Животные звуки") класс Кошка(Животное): звук определения (я): print("Кошка говорит мяу") животное = животное () кошка = кошка () звук животных() кошачий звук()
Вывод:
Звуки животных Кот говорит мяуПолиморфизм времени компиляции
Полиморфизм времени компиляции — это процесс, в котором вызов метода разрешается во время компиляции. Мы реализуем полиморфизм времени компиляции посредством перегрузки методов.
Используя перегрузку методов, вы можете реализовать одну и ту же функциональность класса с другими параметрами. Python не поддерживает полиморфизм во время компиляции, но есть обходной путь, как в примере ниже.
Пример:
класс Пример: def умножить (я, а, б, с = 1): печать (а * б * в) пример=Пример() пример.множить(5,10) пример.множить(2,5,6)
Выход:
50 60Изменяемые и неизменяемые объекты в Python
Изменяемый объект — это изменяемый объект, который можно изменить после его создания. Списки, dict, set и массив байтов — все это изменяемые объекты.
Неизменяемый объект — это объект, состояние которого нельзя изменить после его создания. Целое число, число с плавающей запятой, комплекс, строка Python, кортеж, замороженный набор и байты неизменяемы.
Python обрабатывает изменяемые и неизменяемые объекты по-разному.