Содержание

Конструктор класса – метод __init__(). Урок 3

В объектно-ориентированном программировании конструктором класса называют метод, который автоматически вызывается при создании объектов. Его также можно назвать конструктором объектов класса. Имя такого метода обычно регламентируется синтаксисом конкретного языка программирования. Так в Java имя конструктора класса совпадает с именем самого класса. В Python же роль конструктора играет метод __init__().

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

При этом методы перегрузки операторов не надо вызывать по имени. Вызовом для них является сам факт участия объекта в определенной операции. В случае конструктора класса – это операция создания объекта. Так как объект создается в момент вызова класса по имени, то в этот момент вызывается метод __init__().

Необходимость конструкторов связана с тем, что нередко объекты должны иметь собственные свойства сразу. Пусть имеется класс Person, объекты которого обязательно должны иметь имя и фамилию. Если класс будет описан подобным образом

class Person:
    def set_name(self, n, s):
        self.name = n
        self.surname = s

то создание объекта возможно без полей. Для установки имени и фамилии метод set_name() нужно вызывать отдельно:

>>> from test import Person 
>>> p1 = Person()
>>> p1.set_name("Bill", "Ross")
>>> p1.name, p1.surname
('Bill', 'Ross')

В свою очередь, конструктор класса не позволит создать объект без обязательных полей:

class Person:
    def __init__(self, n, s):
        self.name = n
        self.surname = s
 
 
p1 = Person("Sam", "Baker")
print(p1.name, p1.surname)

Здесь при вызове класса в круглых скобках передаются значения, которые будут присвоены параметрам метода __init__(). Первый его параметр – self – ссылка на сам только что созданный объект.

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

>>> p1 = Person()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 2 required 
positional arguments: 'n' and 's'

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

class Rectangle:
    def __init__(self, w=0.5, h=1):
        self.width = w
        self.height = h
    def square(self):
        return self.width * self.height
 
rec1 = Rectangle(5, 2)
rec2 = Rectangle()
rec3 = Rectangle(3)
rec4 = Rectangle(h=4)
print(rec1.square())
print(rec2.square())
print(rec3.square())
print(rec4.square())

Вывод:

10
0.5
3
2.0

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

Кроме того, конструктору вовсе не обязательно принимать какие-либо параметры, не считая self. Значения полям могут назначаться как угодно. Также не обязательно, чтобы в конструкторе происходила установка атрибутов объекта. Там может быть, например, код, который порождает создание объектов других классов.

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

В Python создать несколько методов __init__() в классе можно, однако «рабочим» останется только последний. Он переопределит ранее определенные. Поэтому в Python в классах используется только один конструктор, а изменчивость количества передаваемых аргументов настраивается через назначение значений по-умолчанию.

Помимо конструктора объектов в языках программирования есть обратный ему метод – деструктор. Он вызывается, когда объект не создается, а уничтожается.

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

В классах Python функцию деструктора выполняет метод __del__().

Напишите программу по следующему описанию:

  1. Есть класс Person, конструктор которого принимает три параметра (не учитывая self) – имя, фамилию и квалификацию специалиста. Квалификация имеет значение заданное по умолчанию, равное единице.

  2. У класса Person есть метод, который возвращает строку, включающую в себя всю информацию о сотруднике.

  3. Класс Person содержит деструктор, который выводит на экран фразу «До свидания, мистер …» (вместо троеточия должны выводиться имя и фамилия объекта).

  4. В основной ветке программы создайте три объекта класса Person. Посмотрите информацию о сотрудниках и увольте самое слабое звено.

  5. В конце программы добавьте функцию input(), чтобы скрипт не завершился сам, пока не будет нажат Enter. Иначе вы сразу увидите как удаляются все объекты при завершении работы программы.

В Python деструктор используется редко, так как интерпретатор и без него хорошо убирает «мусор».

Курс с примерами решений практических работ:
android-приложение, pdf-версия

объекты, встроенные функции и атрибуты

Что такое конструктор в Python?

Конструктор в Python – это особый тип метода (функции), который используется для инициализации членов экземпляра класса.

В C ++ или Java конструктор имеет то же имя, что и его класс, в Python конструктор обрабатывается  по-разному. Он используется для создания объекта.

Конструкторы бывают двух типов:

  1. Параметризованный конструктор
  2. Непараметрический конструктор

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

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

Создание конструктора на Python

В Python метод __init __() имитирует конструктор класса. Этот метод вызывается при создании экземпляра класса. Он принимает ключевое слово self в качестве первого аргумента, который позволяет получить доступ к атрибутам или методу класса.

Мы можем передать любое количество аргументов во время создания объекта класса, в зависимости от определения __init __(). В основном он используется для инициализации атрибутов класса. У каждого класса должен быть конструктор, даже если он просто полагается на конструктор по умолчанию.

Рассмотрим следующий пример для инициализации атрибутов класса Employee при работе с конструкторами в Python.

Пример –

 
class Employee: 
    def __init__(self, name, id): 
        self.id = id 
        self.name = name 
 
    def display(self): 
        print("ID: %d nName: %s" % (self. id, self.name)) 
 
 
emp1 = Employee("John", 101) 
emp2 = Employee("David", 102) 
 
# accessing display() method to print employee 1 information 
 
emp1.display() 
 
# accessing display() method to print employee 2 information 
emp2.display() 

Выход:

ID: 101  
Name: John 
ID: 102  
Name: David 

Подсчет количества объектов класса

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

 
class Student:   
    count = 0   
    def __init__(self):   
        Student.count = Student.count + 1   
s1=Student()   
s2=Student()   
s3=Student()   
print("The number of students:",Student.count)   

Выход:

The number of students: 3 

Непараметрический

Непараметрический конструктор используется, когда мы не хотим манипулировать значением, или конструктором, который имеет только self в качестве аргумента. Разберем на примере.

 
class Student: 
    # Constructor - non parameterized 
    def __init__(self): 
        print("This is non parametrized constructor") 
    def show(self,name): 
        print("Hello",name) 
student = Student() 
student.show("John")     

Параметризованный конструктор Python

У параметризованного конструктора есть несколько параметров вместе с самим собой.

Пример –

 
class Student: 
    # Constructor - parameterized 
    def __init__(self, name): 
        print("This is parametrized constructor") 
        self.name = name 
    def show(self): 
        print("Hello",self.name) 
student = Student("John") 
student.show()   

Выход:

This is parametrized constructor 
Hello John 

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

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

 
class Student: 
    roll_num = 101 
    name = "Joseph" 
 
    def display(self): 
        print(self.roll_num,self.name) 
 
st = Student() 
st.display() 

Выход:

101 Joseph 

Более одного конструктора в одном классе

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

 
class Student: 
    def __init__(self): 
        print("The First Constructor") 
    def __init__(self): 
        print("The second contructor") 
 
st = Student() 

Выход:

The Second Constructor 

В приведенном выше коде объект st вызвал второй конструктор, тогда как оба имеют одинаковую конфигурацию. Первый метод недоступен для объекта st. Внутренне объект класса всегда будет вызывать последний конструктор, если у класса есть несколько конструкторов.

Примечание. Перегрузка конструктора в Python запрещена.

Встроенные функции классов Python

Встроенные функции, определенные в классе, описаны в следующей таблице.

SNФункцияОписание
1getattr(obj,name,default)Используется для доступа к атрибуту объекта.
2setattr(obj, name,value)Она используется для установки определенного значения для определенного атрибута объекта.
3delattr (obj, name)Необходима для удаления определенного атрибута.
4hasattr (obj, name)Возвращает истину, если объект содержит определенный атрибут.

Пример

 
class Student: 
    def __init__(self, name, id, age): 
        self. name = name 
        self.id = id 
        self.age = age 
 
    # creates the object of the class Student 
s = Student("John", 101, 22) 
 
# prints the attribute name of the object s 
print(getattr(s, 'name')) 
 
# reset the value of attribute age to 23 
setattr(s, "age", 23) 
 
# prints the modified value of age 
print(getattr(s, 'age')) 
 
# prints true if the student contains the attribute with name id 
 
print(hasattr(s, 'id')) 
# deletes the attribute age 
delattr(s, 'age') 
 
# this will give an error since the attribute age has been deleted 
print(s.age) 

Выход:

John 
23 
True 
AttributeError: 'Student' object has no attribute 'age' 

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

Наряду с другими атрибутами класс Python также содержит некоторые встроенные атрибуты класса, которые предоставляют информацию о классе.

Встроенные атрибуты класса приведены в таблице ниже.

SNАтрибутОписание
1__dict__Предоставляет словарь, содержащий информацию о пространстве имен класса.
2__doc__Содержит строку с документацией класса.
3__name__Используется для доступа к имени класса.
4__module__Он используется для доступа к модулю, в котором определен этот класс.
5__bases__Содержит кортеж, включающий все базовые классы.

Пример –

 
class Student:   
    def __init__(self,name,id,age):   
        self.name = name;   
        self.id = id;   
        self.age = age   
    def display_details(self):   
        print("Name:%s, ID:%d, age:%d"%(self.name,self.id))   
s = Student("John",101,22)   
print(s. __doc__)   
print(s.__dict__)   
print(s.__module__)   

Выход:

None 
{'name': 'John', 'id': 101, 'age': 22} 
__main__ 

Михаил Русаков

Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.

Еще для изучения:

Объект класса и конструктор класса в Python.

Содержание:
  • Что такое объект класса;
  • Конструктор класса __init__().

Что такое объект класса.

Объект класса в Python представляет собой ИМЯ класса, созданного (определенного/записанного) в коде. Объекты класса поддерживают два вида операций: ссылки на атрибуты и создание экземпляров.

Ссылки на атрибуты используют стандартный синтаксис, используемый для всех ссылок на атрибуты в Python: obj.name. Допустимые имена атрибутов — это все имена, которые были определены в пространстве имен класса при создании объекта класса.

Итак, если определение класса выглядит так:

class MyClass:
    """Простой пример класса"""
    i = 12345
    def f(self):
        return 'hello world'
# `MyClass` - это объект класса
>>> MyClass.i
# 12345
>>> MyClass.f
# <function MyClass.f at 0x7f3c1fd6e840>

то имя MyClass — это объект класса, а MyClass.i и MyClass.f являются действительными ссылками на атрибуты класса, возвращая целое число и функциональный объект соответственно. Атрибуты объекта класса также могут быть присвоены, так что можно изменить значение MyClass.i путем операции присвоения. __doc__ также является допустимым атрибутом, возвращающим строку документации "Простой пример класса", принадлежащую классу MyClass.

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

x = MyClass()
>>> x. i
# 12345
>>> x.f()
# 'hello world'

Конструктор класса

__init__().

Объекты классов обычно создают с экземплярами, настроенными на определенное начальное состояние. Для этого в классе Python определятся специальный метод «конструктор класса» с именем __init__(), который выполняется при создании экземпляра класса. Метод .__init__() принимает новый объект в качестве первого аргумента self.

class MyClass:
    """Простой пример класса"""
    i = 12345
    def __init__(self):
        self.data = []
    def f(self):
        return 'hello world'

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

>>> x = MyClass()
>>> x.data
# []

Метод __init__() может иметь аргументы для большей гибкости. В этом случае аргументы, переданные оператору создания класса, передаются в метод __init__().

Например:

>>> class Complex:
...     def __init__(self, realpart, imagpart):
...         self.r = realpart
...         self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)

Важно отметить, что без учета self, аргументы метода .__init__() — это те же самые аргументы, которые передаются при вызове конструктора класса. Таким образом, сигнатура .__init__() определяет сигнатуру конструктора класса.

Имейте в виду, что конструктор класса .__init__() не должен явно возвращать ничего отличного от None, иначе будет вызываться исключение TypeError:

>>> class Complex:
...     def __init__(self, realpart, imagpart):
...         self.r = realpart
...         self.i = imagpart
...         return realpart + imagpart
>>> x = Complex(3. 0, -4.5)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# TypeError: __init__() should return None, not 'float'

В конструкторе класса .__init__() можно выполнить любое преобразование входных аргументов, чтобы правильно инициализировать атрибуты экземпляра. Например, если пользователи будут использовать класс Rectangle, то например, можно проверить предоставленные ширину и высоту, для того, чтобы убедиться в их верном значении:

>>> class Rectangle:
...     def __init__(self, width, height):
...         if not (isinstance(width, (int, float)) and width > 0):
...             raise ValueError(f"Необходима положительная ширина, получена: {width}")
...         self.width = width
...         if not (isinstance(height, (int, float)) and height > 0):
...             raise ValueError(f"Необходима положительная высота, получена: {height}")
...         self.height = height
>>> rectangle = Rectangle(-21, 42)
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
#   File "<stdin>", line 4, in __init__
# ValueError: Необходима положительная ширина, получена: -21

Теперь предположим, что используется наследование для создания пользовательской иерархии классов и повторного использования некоторых функций в своем коде. Если подклассы предоставляют конструктор .__init__(), то он должен явно вызывать метод .__init__() базового класса с соответствующими аргументами, чтобы обеспечить правильную инициализацию экземпляров. Для этого необходимо использовать встроенную функцию super(), как в следующем примере:

>>> class Person:
...     def __init__(self, name, birth_date):
...         self.name = name
...         self.birth_date = birth_date
>>> class Employee(Person):
...     def __init__(self, name, birth_date, position):
...         super().__init__(name, birth_date)
...         self.position = position
>>> john = Employee("John Doe", "2001-02-07", "Разработчик Python")
>>> john.name
# 'John Doe'
>>> john.birth_date
# '2001-02-07'
>>> john.position
# 'Разработчик Python'

Конструктор класса Python — Python __init __ () Функция

Автор оригинала: Pankaj Kumar.

Функция функции конструктора Python Class – это инициализировать экземпляр класса. Python __init __ () – функция конструктора для классов в Python.

Python __init __ () Функциональный синтаксис

Синтаксис функции __init __ ():

def __init__(self, [arguments])
  • Ключевое слово def используется для определения его, потому что это Функция Отказ
  • Первый аргумент относится к текущему объекту. Это связывает экземпляр к методу init (). Обычно названо «я», чтобы следовать в Конвенции именования. Вы можете прочитать больше об этом на Python самоуправление Отказ
  • Аргументы метода INIT () являются необязательными. Мы можем определить конструктор с любым количеством аргументов.

Примеры конструктора класса Python

Давайте посмотрим на некоторые примеры функции конструктора в разных сценариях.

1. класс без конструктора

Мы можем создать класс без определения конструктора. В этом случае конструктор SuperClass вызывается для инициализации экземпляра класса. объект Класс – это основа всех классов в Python.

class Data:
    pass
d = Data()
print(type(d))  # 

Вот еще один пример, чтобы подтвердить, что конструктор SuperClass вызывается для инициализации экземпляра подкласса.

class BaseData:
    def __init__(self, i):
        print(f'BaseData Constructor with argument {i}')
        self. id = i
class Data(BaseData):
    pass
d = Data(10)
print(type(d))

Выход:

BaseData Constructor with argument 10

2. Простой конструктор без аргументов

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

class Data1:
    count = 0
    def __init__(self):
        print('Data1 Constructor')
        Data1. count += 1
d1 = Data1()
d2 = Data1()
print("Data1 Object Count =", Data1.count)

Выход:

Data1 Constructor
Data1 Constructor
Data1 Object Count = 2

3. Конструктор класса с аргументами

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

class Data2:
    def __init__(self, i, n):
        print('Data2 Constructor')
        self. id = i
        self.name = n
d2 = Data2(10, 'Secret')
print(f'Data ID is {d2.id} and Name is {d2.name}')

Выход:

Data2 Constructor
Data ID is 10 and Name is Secret

4. Класс конструктор с наследством

class Person:
    def __init__(self, n):
        print('Person Constructor')
        self.name = n
class Employee(Person):
    def __init__(self, i, n):
        print('Employee Constructor')
        super(). __init__(n)  # same as Person.__init__(self, n)
        self.id = i
emp = Employee(99, 'Pankaj')
print(f'Employee ID is {emp.id} and Name is {emp.name}')

Выход:

Employee Constructor
Person Constructor
Employee ID is 99 and Name is Pankaj
  • Наша обязанность называть конструктор SuperClass.
  • Мы можем использовать функцию Super () для вызова функции конструктора SuperClass.
  • Мы также можем использовать имя SuperClass, чтобы вызвать его метод init ().

5. Конструктор цепи с многоуровневым наследством

class A:
    def __init__(self, a):
        print('A Constructor')
        self. var_a = a
class B(A):
    def __init__(self, a, b):
        super().__init__(a)
        print('B Constructor')
        self.var_b = b
class C(B):
    def __init__(self, a, b, c):
        super().__init__(a, b)
        print('C Constructor')
        self.var_c = c
c_obj = C(1, 2, 3)
print(f'c_obj var_a={c_obj.var_a}, var_b={c_obj.var_b}, var_c={c_obj.var_c}')

Выход:

A Constructor
B Constructor
C Constructor
c_obj var_a=1, var_b=2, var_c=3

6. Конструктор с несколькими наследованием

Мы не можем использовать Super () для доступа к всем суперклассам в случае нескольких наследований. Лучшим подходом было бы позвонить конструктору функции суперкласс, используя имя своего класса.

class A1:
    def __init__(self, a1):
        print('A1 Constructor')
        self.var_a1 = a1
class B1:
    def __init__(self, b1):
        print('B1 Constructor')
        self.var_b1 = b1
class C1(A1, B1):
    def __init__(self, a1, b1, c1):
        print('C1 Constructor')
        A1.__init__(self, a1)
        B1.__init__(self, b1)
        self.var_c1 = c1
c_obj = C1(1, 2, 3)
print(f'c_obj var_a={c_obj.var_a1}, var_b={c_obj.var_b1}, var_c={c_obj.var_c1}')

Выход:

C1 Constructor
A1 Constructor
B1 Constructor
c_obj var_a=1, var_b=2, var_c=3

Python не поддерживает несколько конструкторов

Python не поддерживает несколько конструкторов, в отличие от других популярных объектно-ориентированных языков программирования, таких как Java.

Мы можем определить несколько методов __init __ (), но последний переопределят более ранние определения.

class D:
    def __init__(self, x):
        print(f'Constructor 1 with argument {x}')
    # this will overwrite the above constructor definition
    def __init__(self, x, y):
        print(f'Constructor 1 with arguments {x}, {y}')
d1 = D(10, 20) # Constructor 1 with arguments 10, 20

Может ли Python __init __ () Функция что-нибудь вернуть?

Если мы попытаемся вернуть значение без значения из функции __init __ (), она будет поднять JypeError.

class Data:
    def __init__(self, i):
        self. id = i
        return True
d = Data(10)

Выход:

TypeError: __init__() should return None, not 'bool'

Если мы изменим оператор возврата в вернуть ни один Затем код будет работать без каких-либо исключения.

Рекомендации:

  • Объект __init __ () Функциональные документы

Классы: введение в объектно-ориентированное программирование

Классы: введение в объектно-ориентированное программирование

Ссылки и объекты

Представление переменных в языке 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
1 2
2 3
2 3

B: Центр масс

Выведите координаты центра масс данного множества точек (учтите, что это —два действительных числа).

Для создания точки определите конструктор, который мог бы принимать на вход как два числа, так и строку. Таким образом, точку можно будет создавать как вызовом Point(x, y), так и Point(input()).

Определите метод __str__ для вывода точки. Определите операции сложения точек, умножения точки на число, деления точки на число.

ВводВывод
2
1 2
2 3
1.5 2.5

C: Диаметр множества

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

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

ВводВывод
3
1 1
1 0
0 0
1.4142135623731

D: Сортировка

Определите для точек операцию сравнения __lt__, сравнивающую точки по значению расстояния от начала координат. Отсортируйте данные точки в порядке возрастания расстояния от начала координат.

ВводВывод
3
1 0
-1 -1
0 0
0 0
1 0
-1 -1

E: Максимальный периметр

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

Для нахождения периметра треугольника напишите отдельную функцию Perimeter(A, B, C).

ВводВывод
4
0 0
0 1
1 0
1 1
3.41421356237309

F: Максимальная площадь

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

Для нахождения площади треугольника напишите отдельную функцию Area(A, B, C).

ВводВывод
4
0 0
0 1
1 0
1 1
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
30/-9
8/4
3
1/2
-10/3
2
3

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

Напомним, что от вас требовалось реализовать конструктор класса Fraction, который принимает на вход разные варанты параметров. В этой задаче проверяется реализация всех этих четырех форм конструктора.

Программа получает на вход текст программы на питоне, использующий различные формы конструктора Fraction и вывод объекта Fraction при помощи функции print. Ваша программа должна считать этот текст и исполнить его при помощи интерпретатора Питона. Это делается так:

exec(stdin.read())
ВводВывод
a = Fraction()
b = Fraction(1)
c = Fraction(1, 3)
d = Fraction('14 35')
e = Fraction('-6/2')
f = Fraction(e)
print(a, b, c, d, e, f, sep='\n')
0
1
1/3
2/5
-3
-3

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 __new__ и функция инициализации __init__ (восемь)

От базового понимания классов до глубокого понимания свойств класса, методов, контроля доступа, наследования, ограничений и т. Д., Как создать класс.

1. Создание и инициализация класса 

Мы определяем класс и генерируем инициализацию_ _init _ _ Функции объекта и _ _ new_ _Объектная функция:

class A(object):
    def __init__(self,*args, **kwargs):
        print ("init %s" %self.__class__)
    def __new__(cls,*args, **kwargs):
        print ("new %s" %cls)
        return object.__new__(cls, *args, **kwargs)
a = A()
new <class '__main__.A'>
init <class '__main__.A'>

Из результата видно, что при создании экземпляра класса A «_ _new _ _ «Сначала вызывается метод, затем -» _ _ init_ _ «метод.

Вообще говоря, «_ _init _ _ «с участием» _ _ new__ «функции будут иметь следующие формы:

def __init__(self, *args, **kwargs):
    # func_suite
def __new__(cls, *args, **kwargs):
    # func_suite
return obj

за»_ _new _ _ «с участием» _ _ init_ _ «можно резюмировать как:

  • _ _new _ _  «Метод в PythonНастоящий метод построения (создать и вернуть экземпляр), С помощью этого методаСгенерируйте объект-экземпляр, соответствующий «cls»,так» _ _ new_ _ «методДолжен быть возвращен
  • За «_ _init _ _ «Метод — это метод инициализации,«Я» означаетГенерация классапублично заявитьизЭкземпляр объекта,” _ _ init_ _» будутИнициализируйте этот объект соответствующим образом

Я уже рассказывал об этом в предыдущей статье «_ _init _ _ «Некоторые акты, в том числе дело о наследстве» _ _ init _ _ «Производительность. Давайте сосредоточимся на этом» _ _ new_ _ «метод.

2、_ _ new__Особенности 
“_ _ new__ «- новый метод, появляющийся в классах нового стиля. Он имеет следующие поведенческие характеристики:

  • “_ _ new__ «Метод — это когда класс создает экземпляр объектаПервый вызванный метод вернет объект-экземпляр
  • “_ _ new__ «Метод всегдаМетод класса (то есть первый параметр — cls), Даже если он не украшен
  • Первый параметр cls — этоКласс, который в настоящее время создается, Если вы хотите получить экземпляр текущего класса, он должен быть в папке «_ _new _ _ «Вызов родительского класса текущего класса в операторе метода» _ _ new__ «Метод

Что касается третьего пункта выше, если текущий класс напрямую наследуется от объекта, то «_new_Объект, возвращаемый методом, должен быть:

def __new__(cls, *args, **kwargs):
  # func_suite
  return object. __new__(cls, *args, **kwargs)

2.1. Rewrite_ _new_ _

в случае(Новый стиль) классНикаких перезаписей в «_ _»new _ _ «Метод, Python по умолчанию вызывает прямой родительский класс этого класса» _ _ new_ _ «Метод создания экземпляра этого класса, если родительский класс этого класса также не переопределен» _ _ new _ _ «Тогда он всегда будет возвращаться к объекту по тем же правилам» _ _new__ «потому чтообъект — это базовый класс всех классов нового стиля

А если его переписать в новом классе «_ _new_ _ «Method, тогда вы можете выбрать любой другой класс нового стиля (Должен быть класс нового стиля, только класс нового стиля имеет «_ _ new_ _ «,потому какВсе классы нового стиля являются производными от объекта) из «__ _ new_ _ «для создания экземпляра, включая все классы-предшественники и потомки этого класса нового стиля, если они не вызывают рекурсивный цикл.

class Fun(object):
    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls, *args, **kwargs)   
        # Здесь объект .__ new __ (cls, * args, ** kwargs) эквивалентен super (Fun, cls) .__ new __ (cls, * args, ** kwargs)   
        # object.__new__(Fun, *args, **kwargs)
#         Ny.__new__(cls, *args, **kwargs)
                 # person .__ new __ (cls, * args, ** kwargs), даже если person не имеет ничего общего с Fun, это разрешено, потому что person - это новый класс, производный от объекта
                 # В любом классе нового стиля вы не можете вызвать его собственный "__new__" для создания экземпляра, потому что это вызовет бесконечный цикл
                 # Так что избегайте return Fun .__ new __ (cls, * args, ** kwargs) или return cls .__ new __ (cls, * args, ** kwargs)
        print("Call __new__ for %s" %obj.__class__)
        return obj    
class Ny(Fun):
    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls, *args, **kwargs)   
        print("Call __new__ for %s" %obj. __class__)
        return obj   
class person(object):
         # person не имеет метода "__new__", тогда метод "__new__" его родительского класса будет автоматически вызван для создания экземпляра, то есть object .__ new __ (cls) будет вызываться автоматически
    pass
class girl(object):
    def __new__(cls, *args, **kwargs):
                 # Вы можете использовать Bar для создания экземпляра
        obj = object.__new__(Ny, *args, **kwargs)   
        print("Call __new__ for %s" %obj.__class__)
        return obj
fun = Fun()
ny = Ny()
girl = girl()
Call __new__ for <class '__main__.Fun'>
Call __new__ for <class '__main__.Ny'>
Call __new__ for <class '__main__.Ny'>

2.2 、_ _ init__ Вызов 
“_ _ new _ _ «Решите, хотите ли вы использовать этот тип» _ _ init_ _ «Метод, потому что» _ _ new_ _ »Вы можете вызывать конструктор других классов или напрямую возвращать объекты, созданные другими классами, как экземпляры этого класса.

Вообще говоря, когда создается экземпляр класса нового стиля, «_ _new_ _ «Метод встречиВозврат cls(cls относится к текущему классу)Экземпляр,тогдаНазовите этот тип «_ _init_ _ «Метод как метод инициализации, Метод получаетЭтот экземпляр (т.е. себя)Как мой первыйпараметр, А затем передать «_ _new»_ _ «Параметры положения и именованные параметры, полученные в методе.

но если»_ _ new _ _ “Не возвращает экземпляр cls (т.е. текущий класс), ПотомТекущий классиз « _ _ init__ «путь естьНе будет называтьсяоф. Взгляните на следующий пример:

class A(object):
    def __init__(self, *args, **kwargs):
        print("Call __init__ from %s" %self.__class__)
    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls, *args, **kwargs)
        print("Call __new__ for %s" %obj.__class__)
        return obj   
class B(object):
    def __init__(self, *args, **kwargs):
        print("Call __init__ from %s" %self. __class__)
    def __new__(cls, *args, **kwargs):
        obj = object.__new__(A, *args, **kwargs)
        print("Call __new__ for %s" %obj.__class__)
        return obj      
b = B()
print(type(b))
Call __new__ for <class '__main__.A'>
<class '__main__.A'>

2.3, производные неизменяемые типы

  • Около «_ _new_Еще одно важное применение метода — получение неизменяемых типов.

Например, float в Python является неизменяемым типом. Если вы хотите наследовать подкласс от float, вы должны реализовать «_ _new_ _ «Метод:

class RoundTFloat(float):
    def __new__(cls, num):
        num = round(num, 4)
        return super(RoundTFloat, cls).__new__(cls, num)
#         return float.__new__(cls, num)
num = RoundTFloat(3.141592654)
print(num)   #3.1416
print(num.__class__)
3.1416
<class '__main__.RoundTFloat'>

3. Настройте класс

  • В Python мы можем сделать специальные классы мощными и простыми в использовании с помощью «волшебных методов».

В статье представлены методы построения и инициализации класса: «_ _new _ _»с участием» _ _ init _ _ “。” _ _ new _ _ «путьНовый стильспециальныйЕстьМетод, как правило, _ _ new _ _ Метод создаст и вернет cls (cls относится к экземпляру текущего класса)А затем позвоните в » _ _ init _ _ «Метод как метод инициализации, метод получает этот экземпляр (т.е. себя) в качестве своего первого параметра, а затем передает его по очереди» _ _ new _ _ «Позиционные и именованные параметры, полученные в методе; но, если» _ _ new _ _ “Нетвозвращениеэкземпляр cls (т.е. текущий класс), Тогда текущая категория » _ _ init_ _ «путь естьНе будет называтьсяоф.

Конструкторы в Python — GeeksforGeeks

Просмотреть обсуждение

Улучшить статью

Сохранить статью

  • Уровень сложности: Easy
  • Последнее обновление: 10 авг, 2021

  • Читать
  • Обсудить
  • Посмотреть обсуждение

    Улучшить статью

    Сохранить статью

    Требования: Объектно-ориентированное программирование на Python, Объектно-ориентированное программирование на Python | Set 2 
    Конструкторы обычно используются для создания экземпляра объекта. Задача конструкторов состоит в том, чтобы инициализировать (присваивать значения) членам данных класса при создании объекта класса. В Python метод __init__() называется конструктором и всегда вызывается при создании объекта.
    Синтаксис объявления конструктора:

     def __init__(self):
        # тело конструктора 

    Типы конструкторов :  

    • конструктор по умолчанию: Конструктор по умолчанию — это простой конструктор, который не принимает никаких аргументов. Его определение имеет только один аргумент, который является ссылкой на создаваемый экземпляр.
    • параметризованный конструктор: конструктор с параметрами известен как параметризованный конструктор. Параметризованный конструктор принимает свой первый аргумент как ссылку на создаваемый экземпляр, известный как self, а остальные аргументы предоставляются программистом.

    Example of default constructor :  
     

    Python3

    class GeekforGeeks:

     

        

         def __init__( self ):

             self . geek = "GeekforGeeks"

    0  6 

    10003

         def print_Geek( self ):

             print ( self .geek)

     

     

    obj = GeekforGeeks ()

     

    obj.print_Geek()

    Вывод :  

    Пример 9 из 9 02035 9 GeekforGeeks0028 parameterized constructor :  

    Python3

    class Addition:

         first = 0

         second = 0

    Ответ = 0

    def

    def 0063 __init__( self , f, s):

             self . first = f

             self .second = s

    DEF Дисплей ( Self ):

    Печать ( " .0063 + STR ( Self . First))

    Print ( "Второй номер =" + ( ". второй))

    Печать ( "Добавление двух чисел =" + Str ( Self 0061      def calculate( self ):

             self . answer = self .first + self .second

    OBJ = Дополнение ( 1000 , 2000 )

    OBJ.CALCULE () 9003

    OBJ.0002

    obj.display()

    Вывод:

     Первое число = 1000
    Второе число = 2000
    Добавление двух чисел = 3000 

     


    Рекомендуемые статьи

    Страница:

    Конструкторы Python - javatpoint

    следующий → ← предыдущая

    Конструктор — это особый тип метода (функции), который используется для инициализации членов экземпляра класса.

    В C++ или Java конструктор имеет то же имя, что и его класс, но в Python он обращается с конструктором иначе. Он используется для создания объекта.

    Конструкторы могут быть двух типов.

    1. Конструктор с параметрами
    2. Конструктор без параметров

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

    Создание конструктора в python

    В Python метод __init__() имитирует конструктор класса. Этот метод вызывается при создании экземпляра класса. Он принимает ключевое слово self в качестве первого аргумента, который позволяет получить доступ к атрибутам или методу класса.

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

    Рассмотрим следующий пример для инициализации атрибутов класса Employee .

    Пример

    класс Сотрудник: def __init__(я, имя, идентификатор): self.id = идентификатор self.name = имя дисплей защиты (я): print("ID: %d \nName: %s" % (self.id, self.name)) emp1 = Сотрудник("Джон", 101) emp2 = Сотрудник("Дэвид", 102) # доступ к методу display() для вывода информации о сотруднике 1 emp1.display() # доступ к методу display() для вывода информации о сотруднике 2 emp2.display()

    Вывод:

     Код: 101
    Имя: Джон
    ID: 102
    Имя: Дэвид
     

    Подсчет количества объектов класса

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

    Пример

    Ученик класса: количество = 0 защита __init__(сам): Счетчик студентов = Счетчик студентов + 1 s1 = Студент () s2=Студент() s3=Студент() print("Количество студентов:",Student.count)

    Вывод:

     Количество студентов: 3
     

    Непараметризованный конструктор Python

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

    Пример

    Ученик класса: # Конструктор - без параметров защита __init__(сам): print("Это непараметризованный конструктор") деф-шоу (я, имя): print("Привет",имя) студент = студент () student.show("Джон")

    Параметризованный конструктор Python

    Параметризованный конструктор имеет несколько параметров вместе с self . Рассмотрим следующий пример.

    Пример

    Ученик класса: # Конструктор - параметризованный def __init__(я, имя): print("Это параметризованный конструктор") self.name = имя деф-шоу (я): print("Привет",self.name) студент = студент ("Джон") студент.шоу()

    Вывод:

     Это параметризованный конструктор
    привет Джон
     

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

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

    Пример

    Ученик класса: рулон_номер = 101 имя = "Джозеф" дисплей защиты (я): печать (self.roll_num, self.name) ст = студент () ул.дисплей()

    Вывод:

     101 Джозеф
     

    Более одного конструктора в одном классе

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

    Пример

    Ученик класса: защита __init__(сам): print("Первый конструктор") защита __init__(сам): print("Второй конструктор") ст = студент ()

    Выход:

     Второй конструктор
     

    В приведенном выше коде объект st вызывает второй конструктор, тогда как оба имеют одинаковую конфигурацию. Первый метод недоступен для объекта st . Внутри объект класса всегда будет вызывать последний конструктор, если класс имеет несколько конструкторов.

    Примечание. В Python не допускается перегрузка конструктора.

    Встроенные функции класса Python

    Встроенные функции, определенные в классе, описаны в следующей таблице.

    Серийный номер Функция Описание
    1 getattr(объект,имя,по умолчанию) Используется для доступа к атрибуту объекта.
    2 setattr(объект, имя,значение) Используется для установки определенного значения для определенного атрибута объекта.
    3 delattr(объект, имя) Используется для удаления определенного атрибута.
    4 hasattr(объект, имя) Возвращает true, если объект содержит определенный атрибут.

    Пример

    Ученик класса: def __init__(я, имя, идентификатор, возраст): self.name = имя self.id = идентификатор возраст = возраст # создает объект класса Student s = Студент ("Джон", 101, 22) # печатает имя атрибута объекта s печать (получить атрибут (ы, 'имя')) # сбросить значение атрибута age на 23 setattr(s, "возраст", 23) # печатает измененное значение возраста print(getattr(s, 'возраст')) # печатает true, если студент содержит атрибут с именем id печать (hasattr (s, 'id')) # удаляет атрибут age delattr(s, 'возраст') # это выдаст ошибку, так как атрибут age был удален печать (s. age)

    Вывод:

     Джон
    23
    Истинный
    AttributeError: объект «Студент» не имеет атрибута «возраст»
     

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

    Наряду с другими атрибутами класс Python также содержит некоторые встроенные атрибуты класса, предоставляющие информацию о классе.

    Встроенные атрибуты класса приведены в таблице ниже.

    Серийный номер Атрибут Описание
    1 __дикт__ Предоставляет словарь, содержащий информацию о пространстве имен классов.
    2 __doc__ Он содержит строку с документацией класса
    3 __имя__ Используется для доступа к имени класса.
    4 __модуль__ Используется для доступа к модулю, в котором определен этот класс.
    5 __базы__ Содержит кортеж, включающий все базовые классы.

    Пример

    Ученик класса: def __init__(я, имя, идентификатор, возраст): self.name = имя; self.id = идентификатор; возраст = возраст определение display_details (я): print("Имя:%s, ID:%d, возраст:%d"%(self.name,self.id)) s = Студент ("Джон", 101,22) печать (s.__doc__) печать (s.__dict__) печать (s.__module__)

    Вывод:

     Нет
    {'имя': 'Джон', 'id': 101, 'возраст': 22}
    __главный__
     

    Следующая темаНаследование Python

    ← предыдущая следующий →

    Конструктор класса Python — функция Python __init__()

    Задача функции конструктора класса Python — инициализировать экземпляр класса. Python __init__() — это функция-конструктор для классов в Python.


    Python __init__() Синтаксис функции

    Синтаксис функции __init__():

     def __init__(self, [arguments])
     
    • Ключевое слово def используется для его определения, поскольку это функция.
    • Первый аргумент относится к текущему объекту. Он привязывает экземпляр к методу init(). Обычно его называют «self», чтобы следовать соглашению об именах. Вы можете прочитать больше об этом в собственной переменной Python.
    • Аргументы метода init() необязательны. Мы можем определить конструктор с любым количеством аргументов.

    Примеры конструктора класса Python

    Давайте рассмотрим несколько примеров функции конструктора в различных сценариях.

    1. Класс без конструктора

    Мы можем создать класс без определения конструктора. В этом случае конструктор суперкласса вызывается для инициализации экземпляра класса. Класс object является основой всех классов в Python.

     класс Данные:
        проходить
    г = данные ()
    print(type(d)) # <класс '__main__.Data'>
     

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

     класс Базовые данные:
        защита __init__(я, я):
            print(f'Конструктор BaseData с аргументом {i}')
            self. id = я
    данные класса (базовые данные):
        проходить
    г = данные (10)
    печать (тип (г))
     

    Вывод:

     Конструктор BaseData с аргументом 10
    <класс '__main__.Данные'>
     

    2. Простой конструктор без аргументов

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

     класс Данные1:
        количество = 0
        защита __init__(сам):
            print('Конструктор Data1')
            Данные1.счет += 1
    d1 = Данные1()
    d2 = Данные1()
    print("Счетчик объектов Data1 =", Data1.count)
     

    Вывод:

     Конструктор Data1
    Конструктор данных1
    Количество объектов Data1 = 2
     

    3. Конструктор класса с аргументами

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

     класс Данные2:
        def __init__(я, я, п):
            print('Конструктор Data2')
            self. id = я
            само.имя = п
    d2 = Данные2(10, 'Секрет')
    print(f'Идентификатор данных – {d2.id}, а имя – {d2.name}')
     

    Вывод:

     Конструктор Data2
    Идентификатор данных — 10, а имя — секрет
     

    4. Конструктор класса с наследованием

     класс Person:
        защита __init__(я, п):
            print('Конструктор персонажей')
            само.имя = п
    класс Сотрудник (Человек):
        def __init__(я, я, п):
            print('Конструктор сотрудников')
            super().__init__(n) # то же, что и Person.__init__(self, n)
            self.id = я
    эмп = Сотрудник (99, «Панкай»)
    print(f'Идентификатор сотрудника – {emp.id}, а имя – {emp.name}')
     

    Вывод:

     Сотрудник Конструктор
    Конструктор лица
    Идентификатор сотрудника — 99, имя — Панкадж.
     
    • Мы обязаны вызвать конструктор суперкласса.
    • Мы можем использовать функцию super() для вызова функции конструктора суперкласса.
    • Мы также можем использовать имя суперкласса для вызова его метода init().

    5. Цепочка конструкторов с многоуровневым наследованием

     класс А:
        def __init__(я, а):
            print('Конструктор')
            self.var_a = а
    класс Б(А):
        def __init__(я, а, б):
            супер().__init__(а)
            print('Конструктор Б')
            self.var_b = б
    класс С(В):
        def __init__(я, а, б, в):
            супер().__init__(а, б)
            print('Конструктор Си')
            self.var_c = с
    c_obj = С (1, 2, 3)
    print(f'c_obj var_a={c_obj.var_a}, var_b={c_obj.var_b}, var_c={c_obj.var_c}')
     

    Выход:

     Конструктор
    Б Конструктор
    C Конструктор
    c_obj var_a=1, var_b=2, var_c=3
     

    6. Конструктор с множественным наследованием

    Мы не можем использовать super() для доступа ко всем суперклассам в случае множественного наследования. Лучшим подходом было бы вызвать функцию-конструктор суперклассов, используя имя их класса.

     класс А1:
        защита __init__(я, a1):
            print('Конструктор A1')
            self. var_a1 = a1
    класс В1:
        защита __init__(я, b1):
            print('Конструктор B1')
            self.var_b1 = b1
    класс С1(А1, В1):
        def __init__(я, a1, b1, c1):
            print('Конструктор C1')
            A1.__init__(самостоятельно, a1)
            B1.__init__(самостоятельно, b1)
            self.var_c1 = c1
    c_obj = C1 (1, 2, 3)
    print(f'c_obj var_a={c_obj.var_a1}, var_b={c_obj.var_b1}, var_c={c_obj.var_c1}')
     

    Вывод:

     Конструктор C1
    Конструктор А1
    Конструктор Б1
    c_obj var_a=1, var_b=2, var_c=3
     

    Python не поддерживает несколько конструкторов

    Python не поддерживает несколько конструкторов, в отличие от других популярных объектно-ориентированных языков программирования, таких как Java.

    Мы можем определить несколько методов __init__(), но последний из них переопределит более ранние определения.

     класс D:
        защита __init__(я, х):
            print(f'Конструктор 1 с аргументом {x}')
        # это перезапишет указанное выше определение конструктора
        def __init__(я, х, у):
            print(f'Конструктор 1 с аргументами {x}, {y}')
    d1 = D(10, 20) # Конструктор 1 с аргументами 10, 20
     

    Может ли функция Python __init__() что-то вернуть?

    Если мы попытаемся вернуть значение, отличное от None, из функции __init__(), это вызовет TypeError.

     класс Данные:
        защита __init__(я, я):
            self.id = я
            вернуть Истина
    г = данные (10)
     

    Вывод:

     TypeError: __init__() должен возвращать None, а не 'bool'
     

    Если мы изменим оператор return на return None , тогда код будет работать без каких-либо исключений.


    Ссылки:

    • object __init__() function docs

    __init__ в Python: обзор

    Сегодня каждый программист в течение своей карьеры обязательно сталкивается с объектно-ориентированным программированием (ООП). Как современный язык программирования, Python предоставляет все средства для реализации объектно-ориентированной философии. Метод __init__ лежит в основе ООП и требуется для создания объектов.


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

    Что такое объектно-ориентированное программирование?

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

    Для объявления, инициализации и управления объектами в Python мы используем классы. Они служат шаблонами, на основе которых создаются объекты. Следующая диаграмма иллюстрирует эту идею:

    На приведенной выше диаграмме видно, что класс собак содержит определенные характеристики собак, такие как порода и цвет глаз, а также способности бегать и ходить. Начнем с определения класса в Python.

    Что такое класс?

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

    Пользовательские и специальные методы

    Методы — это функции внутри класса, предназначенные для выполнения определенной задачи. Python различает пользовательские методы, написанные программистом, и специальные методы, встроенные в язык. Пользовательский метод — это функция, созданная программистом для определенной цели. Например, класс dog может иметь метод walk() , который может использовать объект собаки. Программист создает этот метод и заставляет его выполнять определенные действия.

    Специальные методы обозначаются двойным подчеркиванием с обеих сторон их имени, например, __init__ . Python использует специальные методы для расширения функциональности классов. Большинство из них работают в фоновом режиме и вызываются автоматически, когда это необходимо программе. Вы не можете вызывать их явно. Например, когда вы создаете новый объект, Python автоматически вызывает метод __new__ , который, в свою очередь, вызывает метод __init__ . __str__ метод вызывается, когда вы печатаете() объект. С другой стороны, пользовательские методы, такие как stefi.run() , вызываются явно.

    Конструктор

    Конструктор — это специальный метод, который программа вызывает при создании объекта. Конструктор используется в классе для инициализации элементов данных в объекте. В нашем примере класса собаки вы можете использовать конструктор для назначения характеристик собаки каждому фокстерьеру 9.0063 объект. Специальный метод __init__ — это конструктор Python.

    Имея представление об объектно-ориентированном программировании и классах, давайте теперь посмотрим, как метод __init__ работает в программе Python.

    Важность объектов в Python

    Мы не всегда замечаем это, когда пишем программу, но объекты занимают центральное место в работе Python. Когда мы объявляем простую переменную в Python, в фоновом режиме создается объект.

    Если мы выполним следующий бит кода:

    порода = "Доберман"
     


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

    Как работает метод __init__?

    Метод __init__ является Python-эквивалентом конструктора C++ в объектно-ориентированном подходе. Функция __init__   вызывается каждый раз, когда объект создается из класса. __init__ позволяет классу инициализировать атрибуты объекта и не служит никакой другой цели. Он используется только внутри классов.

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

    Начнем с создания класса:

    класс Собака:
    def __init__(self,dogBreed,dogEyeColor):
     
        self.breed = собачья порода
        self.eyeColor = dogEyeColor...
     

    Сначала мы объявляем класс Dog с помощью ключевого слова class . Мы используем ключевое слово def для определения функции или метода, например, __init__ метод. Как видите, метод __init__ инициализирует два атрибута: порода и eyeColor .

    Теперь посмотрим, как передать эти параметры при объявлении объекта. Здесь нам нужно ключевое слово self для привязки атрибутов объекта к полученным аргументам.

    Создать объект

    Далее мы создадим объект или экземпляр класса Собака :

    ...Томита = Собака("Фокстерьер","коричневый")...
     

    Когда мы создаем объект tomita (имя собаки), мы сначала определяем класс, из которого он создан ( Dog ). Затем мы передаем аргументы «Фокстерьер» и «коричневый», которые соответствуют соответствующим параметрам метода __init__ класса Dog .

    Метод __init__ использует ключевое слово self для присвоения значений, переданных в качестве аргументов, атрибутам объекта self. breed и self.eyeColor .

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

    Чтобы получить доступ к атрибуту вашего нового объекта Fox Terrier, вы можете использовать нотацию с точкой (.), чтобы получить нужное вам значение. Оператор печати помогает нам продемонстрировать, как это работает:

    .
    ...print("Эта собака - ",tomita.breed," и у нее глаза, "tomita.eyeColor")
     

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

    Эта собака - фокстерьер, и у нее карие глаза.
     

    Программа получила доступ к атрибутам tomita и правильно отобразила их.

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

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

    .
    класс Собака:
    def __init__(self, dogBreed="Немецкая овчарка",dogEyeColor="Коричневый"):
     
        self. breed = собачья порода
        self.eyeColor = собакаEyeColor
     

    Если пользователь не введет никаких значений, конструктор присвоит атрибутам «Немецкая овчарка» и «Коричневый».

    Теперь мы можем создать экземпляр Dog без указания каких-либо параметров: 

    Томита = Собака()
     

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

    print("Эта собака - ",tomita.breed,"и её глаза,"tomita.eyeColor)
     

    Это дает нам следующий вывод:

    Эта собака — немецкая овчарка, и у нее карие глаза.
     

    Этот простой код отлично работает.

    Научитесь программировать с помощью Udacity

    Метод __init__ имеет первостепенное значение для объектно-ориентированного программирования Python. В этой статье мы объяснили роль метода __init__ в контексте ООП и определения класса. Метод __init__ является одним из многочисленных специальных методов, встроенных в Python, и программисты могут использовать его с параметрами или без них для каждого создаваемого ими класса.

    Хотите действительно поднять свои навыки программирования на новый уровень?

    Наша программа «Введение в программирование» Наноградус — ваш следующий шаг. Мы научим вас основам кодирования, и вы будете думать и решать проблемы, как программист!

    Пример полного кода

    Пример 1:

    класс Собака:
    def __init__(self, dogBreed,dogEyeColor):
     
        self.breed = собачья порода
        self.eyeColor = собакаEyeColor
    tomita = Собака ("Фокстерьер", "коричневый")
    print("Эта собака - ",tomita.breed,"и глаза у нее ",tomita.eyeColor)
     

    Пример 2:

    класс Собака:
    защита __init__(сам):
        self.nbLegs = 4
    Томита = Собака()
    print("У этой собаки есть",tomita.nbLegs,"ноги")
     


    Пример 3:
    класс Собака:
    def __init__(self, dogBreed="Немецкая овчарка",dogEyeColor="brown"):
     
        self.breed = собачья порода
        self.eyeColor = собакаEyeColor
    Томита = Собака()
    print("Эта собака - ",tomita.breed,"и глаза у нее ",tomita. eyeColor)
     

    Python: __init__() не единственный конструктор

    Многие новички и даже Pythonic-программисты думают, что __init__() является конструктором, поскольку он инициализирует значения при вызове, но __init__() является специальным методом , который инициализирует объекты и немедленно вызывается, когда объект создается и инициализируется и не выделяет память. Так что это не единственный метод для конструктора.

     класс Foo:
      def __init__(я, значение_a, значение_b):
        self.a = значение_a
        self.b = значение_b
    Фу = Фу(7, 9) # __init__ вызывается
    print(foo.a, foo.b) # 7, 9
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    __new__() Метод вызывается перед действием __init__() . Это связано с тем, что __new__() выделяет память до вызова __init__() .

     по определению __new__(cls, *args, **kwargs)
     
    Войти в полноэкранный режимВыйти из полноэкранного режима __new__() всегда вызывается перед __init__() .
  • Первый аргумент — это сам класс, который передается неявно.
  • Всегда возвращайте допустимый объект из нового (). Не обязательно, но в этом весь смысл.
  • __new__() управляет созданием объекта. Это означает, что в крайнем случае вы можете вернуть в конце объект совершенно другого типа. Скоро приведу пример.
  •  класс Точка():
        def __new__(cls,*args,**kwargs):
            print("Из нового")
            печать (клс)
            печать (аргументы)
            печать (kwargs)
            # создаем наш объект и возвращаем его
            obj = super().__new__(cls)
            вернуть объект
        def __init__(я, х = 0, у = 0):
            print("Из инициализации")
            я.х = х
            селф.у = у
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Вывод:

     >>> p2 = Point(3,4)
    Из нового
    <класс '__main__.Point'>
    (3, 4)
    {}
    Из инициализации
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Мы видим, что __new__() вызывается перед __init__() при инициализации объекта, а также видим, что параметр cls в __new__() является самим классом (точка ). Наконец, объект создается вызовом функции __new__() 9.0063 для базового класса объекта. В Python объект — это базовый класс, от которого унаследованы все остальные классы. В приведенном выше примере мы сделали это, используя super() .

    Когда использовать __init__() и __new__() ?

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

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

    Ограничить количество создаваемых объектов

    Предположим, мы хотим создать класс RectPoint для создания экземпляров, представляющих четыре вершины квадрата. Мы можем наследоваться от нашего предыдущего класса Point (первый пример в этой статье) и использовать новый () для реализации этого ограничения. Вот пример ограничения класса только четырьмя экземплярами.

     класс RectPoint(точка):
        МАКС_Инст = 4
        Inst_created = 0
        def __new__(cls,*args,**kwargs):
            если (cls.Inst_created >= cls.MAX_Inst):
                поднять ValueError("Невозможно создать больше объектов")
            cls.Inst_created += 1
            вернуть super().__new__(cls)
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Пример запуска.

     >>> p1 = RecPoint(0,0)
    >>> p2 = прямая точка (1,0)
    >>> p3 = прямая точка (1,1)
    >>> p4 = прямая точка (0,1)
    >>>
    >>> p5 = прямая точка (2,2)
    Traceback (последний последний вызов):
    ...
    ValueError: невозможно создать больше объектов
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Простой синглтон

    В этом вы должны быть осторожны в __init__() , потому что он вызывается каждый раз, когда вы «создаете экземпляр» объекта (т. е. вы делаете a = Example() ), даже если они возвращают один и тот же объект.

    _синглтон = Нет
    Пример класса:
        защита __new__(cls):
            глобальный _singleton
            если _singleton равен None:
                _singleton = super(Пример, cls).__new__(cls)
            вернуть _singleton
    а = Пример()
    б = Пример()
    а есть б
    # вывод: Истина
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Возврат полностью нового объекта

    В этом примере будет вызываться int.__init__() , а не Example.__init__() , поскольку возвращаемый объект имеет тип не Example , а int .

     класс Пример:
        защита __new__(cls):
            вернуть 3
    тип(пример())
    # вывод: целое
     
    Войти в полноэкранный режимВыйти из полноэкранного режима

    Таким образом, оба __new__() и __init__() работает и функционирует как конструктор из другого языка ООП, такого как C++, поскольку он выделяет и инициализирует объекты. Но поскольку __init__() в основном используется, как указано выше. Вы можете назвать __init__() "конструктором", так как нас не волнует распределение. Python — очень абстрактный язык, и нам не нужно особо заботиться о памяти.

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

    Создание и использование объектов класса Python и итераторов

    • Мотивирующий пример
    • Введение
      • Объекты Python
      • Атрибуты объекта
      • Соглашения об именах атрибутов
    • Конструкторы классов
      • Объекты класса против конструкторов
      • Методы класса
    • Специальные методы для объектов класса
      • __init__ Метод
      • Итераторы: __iter__ и __следующий__
      • __каталог__ Метод
    • Наследование класса
    • Изменение имени атрибута
    • Пример объектов класса
    • Практические задачи

    Объекты класса Мотивирующий пример

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

    Студент Всего домашних заданий (20%) Проект 1 (10%) Среднесрочная (20%) Проект 2 (10%) Финал (40%)
    Мэри 85 90 88 100 90
    Мэтью 80 95 70 90 70
    Мари 90 92 84 0 91
    Мануэль 79 70 85 70 82
    Малала 100 95 100 98 99

    Теперь нам нужно вычислить сводную статистику по каждому ученику в классе. Для этого мы будем использовать новую форму хранения данных и методов, называемую объектом класса. С объектами классов мы можем разрабатывать новые и эффективные алгоритмы выполнения задач.


    Введение в объекты Python

    В нескольких последних руководствах мы описывали различные «вещи» Python, такие как типы данных, структуры и функции, как «объекты». В первом руководстве мы также представили, что Python — это «объектно-ориентированный» язык сценариев. Тема объектно-ориентированного программирования широка, и этот учебник не будет пытаться охватить ее полностью. Тем не менее, мы рассмотрим основы объектно-ориентированного программирования, связанные с Python, и рассмотрим 9Конструктор 0062 класса подробно описан в этом руководстве.


    Получите наш комплект разработчика Python бесплатно

    Я собрал комплект разработчика Python с более чем 100 готовыми сценариями Python, охватывающими структуры данных, Pandas, NumPy, Seaborn, машинное обучение, обработку файлов, веб-скрапинг и многое другое — и я хочу, чтобы вы получили его бесплатно. Введите свой адрес электронной почты ниже, и я вышлю вам копию.


    Объекты Python

    Объекты Python — это переменные, классы, функции и другие «вещи», которые поддерживают некоторый указатель (где он находится), содержат некоторые данные и могут содержать внутренние процедуры или методы. Например, давайте создадим строковый объект:

     x = "string" # Создание экземпляра объекта и назначение указателя на x
    id("string"), id(x) # Проверяем, что x указывает на один и тот же объект
    > (3106053026736, 3106053026736) 

    Когда мы используем кавычки, Python создает или «создает экземпляр» строкового объекта. Если мы хотим найти, где объект находится в памяти, чтобы использовать его, нам нужно будет создать «указатель» на строковый объект. Мы создали приведенный выше указатель, используя оператор присваивания = , чтобы назначить переменную x в качестве указателя на созданный строковый объект. Мы можем сказать, что 9Переменная 0062 x указывает на тот же строковый объект, используя функцию id .


    Атрибуты объекта

    «Атрибут» объекта — это некоторое значение или метод, присоединенный к этому объекту. В некотором смысле атрибут — это набор переменных и функций, определенных в «песочнице» объекта. Когда функция является атрибутом объекта, она называется «методом». На атрибуты объекта в Python ссылаются, используя соглашение object.attribute . Мы можем просмотреть все атрибуты, связанные с объектом, используя встроенный директор() функция 1 .

     директор(х)
    > ['__добавить__',
    > '__класс__',
    > '__содержит__',
    > '__делатр__',
    > '__дир__',
    > '__doc__',
    > '__экв__',
    > ... # Опускаем дальнейшие результаты 

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

    Например, если я хочу сделать все буквы в созданной нами строке прописными, то я могу вызвать метод upper :

     х. верхний
    > <функция ул.верхняя>
    х.верхний()
    > "СТРОКА" 

    Как мы упоминали ранее в нашем руководстве по функциям, важно знать, что на метод ссылается x.upper , а вызывается или «активируется» x.upper() .


    Соглашения об именах атрибутов

    Многие новички в Python могут быть сбиты с толку запутанным соглашением об именах, используемым Python для атрибутов объекта. В приведенном выше примере со строками строковый объект имел атрибуты 9.0062 x.__dir__ и x.upper . Почему символы подчеркивания были добавлены к объекту dir , а не к объекту upper ? Причина в соглашении Python по классификации атрибутов объекта.

    В следующей таблице приведены сводные данные об этом соглашении для примера атрибута atr :

    .
    Имя Пример Причина
    Одиночное подчеркивание в начале _atr Объявление «частных» переменных или только для внутреннего использования
    Одиночное подчеркивание в конце атр_ Предотвращает конфликт со встроенными ключевыми словами
    Двойное подчеркивание в начале __атр Имя атрибута "коверкать"
    Двойное подчеркивание в начале и конце __атр__ Специальное внутреннее использование Python

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

    Одиночные знаки подчеркивания в конце используются, чтобы отличать имена атрибутов от других встроенных имен Python. Например, если бы я хотел, чтобы метод с именем выводил , но не хотел вызывать встроенную функцию Python print , тогда я мог бы назвать атрибут print_ .

    Двойные начальные символы подчеркивания указывают Python, что имя, на которое делается ссылка, должно быть «искажено» или изменено с использованием имени класса. Например, атрибут с именем __atr внутри объекта может быть доступен только вне объекта с помощью object._ClassName__atr . Мы рассмотрим их более подробно позже.

    Двойные начальные и конечные символы подчеркивания предназначены для внутренних функций и обработки Python. Как мы видели выше, 9Встроенная функция Python 0062 dir работает путем доступа к атрибуту object. __dir__ . Поскольку эти атрибуты в основном используются самим Python, они редко создаются пользователями.


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

    Теперь, когда мы поговорили об объектах Python, которые уже существуют в Python, давайте рассмотрим, как мы можем создавать новые объекты для себя. Мы можем определить новые объекты класса, используя конструктор объектов класса класса . класс 9Конструктор объекта 0063 имеет следующий формат:

     класс [имя]:
    [внутренности] 

    Аналогично , если инструкции и циклы, строки с отступом (табуляция или 4 пробела), следующие за открывающей строкой, сгруппированы внутри конструктора.

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

    Пример класса
    :
    ключ = "пример строки" 

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

     х = пример()
    х.добавленное значение = 1000
    печать (x.добавленное значение)
    > 1000 

    Поэтому мы можем хранить переменные в самих объектах класса.


    Объекты класса против конструкторов

    В приведенном выше примере мы создали конструктор класса с именем example . Распространенной ошибкой новичков в Python является предположение, что конструктор класса является объектом класса. Это не тот случай. Конструктор формирует шаблон объекта класса, на котором создаются или реализуются объекты класса. Например, если мы создадим пример объекта , создав его экземпляр и назначив его переменной x , мы можем ссылаться на ключевой атрибут и манипулировать им:

    Пример класса
    :
    ключ = "пример строки"
    x = example() # Создать экземпляр объекта класса и присвоить x
    печать (х.ключ)
    >пример строки
    x.key = "object string" # Изменение атрибута ключа
    печать (х. ключ)
    > строка объекта
    print(example.key) # Обратите внимание, что атрибут объекта не изменил атрибут конструктора
    > строка примера 

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

     х = пример()
    у = пример ()
    x.key = "Один пример"
    y.key = "Другой пример"
    печать (х.ключ)
    > Один пример
    печать (y.key)
    > Другой пример 

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


    Получите наш комплект разработчика Python бесплатно

    Я собрал комплект разработчика Python с более чем 100 готовыми сценариями Python, охватывающими структуры данных, Pandas, NumPy, Seaborn, машинное обучение, обработку файлов, веб-скрапинг и многое другое — и я хочу, чтобы вы получили его бесплатно. Введите свой адрес электронной почты ниже, и я вышлю вам копию.


    Методы класса

    Ранее мы упоминали, что функции могут быть включены в качестве атрибутов объекта в так называемые методы. Мы можем сделать это, просто определив функцию в конструкторе класса:

    Пример класса
    :
    ключ = "пример строки"
    def addup(self, a, b): # Мы объясним оператор "self" через мгновение.
    возврат (а + б)
    x = example() # инициализация объекта
    х.сложение(3,2)
    > 5 

    С небольшим изменением во входном кортеже мы воссоздали функцию для суммирования двух чисел как метод объекта. Однако вы можете задаться вопросом, почему мы хотим создать этот метод, а не просто создать функцию. Секрет кроется в self переменная в кортеже ввода метода.

    Всякий раз, когда метод определяется в объекте класса класса , первым входным объектом всегда будет переменная self 3 . Мы можем представить, что переменная self относится к самому объекту. Это означает, что на любой атрибут, определенный как часть объекта, можно ссылаться внутри объекта как self . Например:

    Пример класса
    :
    значение = 3
    def addup(я, а):
    return(a + self.value) # Теперь мы добавим заданное значение к внутреннему значению
    x = example() # инициализация объекта
    х.сложение(2)
    > 5
    x.value = 8 # Мы можем изменить внутреннюю переменную value, используя атрибут x.value
    х.сложение(2)
    > 10 

    Другими словами, когда мы вызываем self в конструкторе класса, мы говорим Python использовать атрибут того же объекта. Поскольку мы можем создать экземпляр объекта для любой переменной ( x , y и т. д.), тогда self обеспечивает согласованный способ ссылки на объект из конструктора.


    Специальные методы для объектов класса

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


    __init__ Метод

    Метод __init__ — это стандартный метод, который Python использует при создании экземпляра (или инициализации) и объекта. Предположим, мы создаем экземпляр следующего объекта класса х = пример() . Когда мы вызываем конструктор с помощью example() , Python будет искать в объекте метод __init__ и автоматически выполнять его содержимое с инстанцирующим входным кортежем. Например:

    Пример класса
    :
    def __init__(self, input): # Не забудьте поставить себя первым!
    self.key = ввод
    print(example.key) # Проверяем, есть ли у конструктора ключ. Это должно потерпеть неудачу. 
    > AttributeError: тип объекта «пример» не имеет атрибута «ключ»
    x = example("sample text") # Создайте экземпляр объекта класса и используйте следующий ввод в __init__
    печать (х.ключ)
    > образец текста 

    Большая часть использования объекта класса включает __init__ , так как он используется для настройки объекта для последующего использования.


    Итераторы: __iter__ и __next__

    В предыдущем руководстве по функциям мы подробно обсуждали функции-генераторы и их использование. Мы расширим концепцию генератора до более общего класса объектов-итераторов. Генераторные функции — это краткий способ определения итератора; однако, если требуется более сложный процесс итерации, мы можем создать итератор.

    Метод __init__ в объекте сообщит Python, что объект является итерируемым и может вызываться с помощью функции iter . Например, объекты списка обладают методом __iter__ , поэтому мы можем перебирать их, используя оператор for. .. in... .

    Метод __next__ сообщает Python, какие действия следует выполнять при выполнении следующего вызова итерации над объектом. Этот метод обеспечивает те же возможности, что и , в то время как 9Цикл 0063 в сочетании с оператором yield для генераторов.

    Начнем с создания собственного итератора для вывода списка строк.

     класс myIterator:
    def __init__(self, input): # __init__ для чтения списка ввода
    self.listing = ввод
    self.max = len(input) # начать индекс
    селф.индекс = -1
    защита __iter__(я):
    return(self) # Это просто указывает объект обратно на себя при вызове
    def __next__(self): # Основной итерационный цикл
    self.index += 1 # Увеличиваем индекс на 1 в каждом цикле
    if self.index >= self.max: # Если мы достигли конца списка элементов
    поднять StopIteration # Это остановит итерацию после того, как список будет исчерпан
    возврат (я. листинг [я. индекс])
    
    listing = ["The", "best", "of", "times."]
    x = мой итератор (листинг)
    для элемента в x:
    печать (элемент)
    >
    > лучший
    > из
    > раз.  

    Обратите внимание, что в приведенном выше примере мы сохранили условие в методе __next__ , чтобы вызвать исключение, чтобы остановить выполнение итератора, как только все элементы будут исчерпаны. Это похоже на остановку, которую мы добавили в функцию-генератор, чтобы предотвратить бесконечные циклы. Пока не беспокойтесь о том, что влечет за собой оператор поднять ; мы подробно обсудим исключения в следующем уроке.


    __dir__ Метод

    Ранее мы упоминали dir 9.0063 и как она проверяет объект на наличие метода __dir__ для вывода списка всех доступных методов. Мы можем сами настроить этот список внутри объекта:

    Пример класса
    :
    защита __init__(сам):
    селф.ключ = 1000
    ключ печати (я):
    печать (самостоятельный ключ)
    защита __dir__(я):
    return(["__init__", "__dir__", "printkey"])
    х = пример ()
    реж (х)
    > ['__dir__', '__init__', 'printkey'] 

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

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

    Пример класса
    Parent:
    основной ключ = 1000
    
    пример классаChild (exampleParent):
    дочерний ключ = 2
    x = exampleChild() #Обратите внимание, что нам нужно только вызвать родительский класс в конструкторе
    печать (x.mainKey)
    > 1000
    печать (x.childKey)
    > 2 

    Обратите внимание, что в приведенном выше примере объект exampleChild сам не определяет атрибут mainKey , а скорее «унаследовал» атрибут от родительского класса. Наследование особенно полезно в ситуациях, когда несколько классов используют одни и те же методы. Вместо повторного ввода этих методов в каждом классе вы можете определить родительский класс с общими методами и наследовать их дочерним объектам.


    Изменение имени атрибута

    Во введении мы видели, что соглашение об именах с подчеркиванием __atr информирует Python о необходимости «искажать» имя атрибута при создании экземпляра объекта. Это означает, что имя атрибута будет преобразовано в _ClassName__atr для справки. Например,

    Пример класса
    :
    деф обычноеИмя(я):
    селф.ключ = 1
    def __mangledName(я):
    самостоятельная ценность = 1
    х = пример ()
    печать (режим (х))
    > [...'_example__mangledName', 'regularName'] # другой вывод 

    Как видно из вышеизложенного, __mangledName было преобразовано в _example__mangledName . Обычно эта форма искажения имени используется для классификации атрибута объекта как частного. Он также используется для предотвращения конфликтов имен между экземплярами классов.


    Пример объектов класса

    Теперь, когда мы изучили основы объектов Python и конструктора объектов класса, давайте вернемся к нашему мотивирующему примеру с классом географии. Мы хотим создать способ хранения атрибутов учащихся и выполнения вычислений на основе этой информации.

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

     geographyClass = [{"Имя":"Мария","HW":85,"P1":90,"M":88,"P2":100,"F":90},
    {"Имя":"Мэтью" ,"HW":80 ,"P1":95 ,"M":70 ,"P2":90 ,"F":70},
    { "Имя": "Мария", "HW": 90, "P1": 92, "M": 84, "P2": 0, "F": 91},
    {"Имя":"Мануэль" ,"HW":79 ,"P1":70 ,"M":85 ,"P2":70 ,"F":82},
    {"Имя":"Малала","HW":100,"P1":95,"M":100,"P2":98,"F":99}] 

    Мы можем создавать объекты, установив geographyStudent класс, содержащий атрибуты для ввода из словаря:

     класс географияУченик:
    def __init__(self, input): #Инициализация каждого атрибута оценки
    self. name = ввод["Имя"]
    self.homework = ввод["HW"]
    self.project1 = ввод["P1"]
    self.midterm = ввод ["M"]
    self.project2 = ввод["P2"]
    self.final = ввод ["F"] 

    Теперь мы можем добавить данные в список объектов класса geographyStudent .

     student = [] # Определяем пустой список для размещения объектов
    для s в классе географии:
    student.append(geographyStudent(s)) # Создаем экземпляр объекта для каждого учащегося
    печать (студенты)
    > [<__main__.geographyStudent в 0x190feca1d30>,
    > <__main__.geographyStudent по адресу 0x190feca1d68>,
    > <__main__.geographyStudent по адресу 0x190feca1da0>,
    > <__main__.geographyStudent по адресу 0x190feca1dd8>,
    > <__main__.geographyStudent по адресу 0x190feca1e10>]
    печать (студенты [0]. имя)
    > Мэри 

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

     класс географияУченик:
    def __init__(self, input): #Инициализация каждого атрибута оценки
    self. name = ввод["Имя"]
    self.homework = ввод["HW"]
    self.project1 = ввод["P1"]
    self.midterm = ввод ["M"]
    self.project2 = ввод["P2"]
    self.final = ввод["F"]
    Def finalGrade (я):
    self.grade = (self.homework*0.2
    + селф.проект1*0.1
    + самостоятельная среднесрочная*0,2
    + селф.проект2*0.1
    + сам.финал*0.4)
    возврат (самооценка)
    
    студенты = []
    оценки = []
    для s в классе географии:
    student.append(географияСтудент(ы))
    для s у студентов:
    оценки.append(s.finalGrade())
    печать (оценки)
    > [89.6, 76,5, 80,4, 79,6, 98,9] 

    Получите наш комплект разработчика Python бесплатно

    Я собрал комплект разработчика Python с более чем 100 готовыми сценариями Python, охватывающими структуры данных, Pandas, NumPy, Seaborn, машинное обучение, обработку файлов, веб-скрапинг и многое другое — и я хочу, чтобы вы получили его бесплатно. Введите свой адрес электронной почты ниже, и я вышлю вам копию.


    Практические задачи Python Objects
    1. Создайте объект класса, поддерживающий свойства двусвязного списка. Основным объектом должен быть список, а каждый элемент списка должен быть объектом с ключ , следующий и предыдущий атрибуты. Используйте None в качестве нулевого объекта. Решение

    2. Предположим, что у каждого ученика упомянутой выше школы есть атрибут x.school = "Example High" . Создайте объект класса, определяющий этот более общий атрибут учащегося, и заново создайте объект geographyStudent сверху, который наследует его. Решение

    3. Список всех методов, связанных с объектами Boolean, Integer и Float. Решение

    4. Рассмотрим следующий код Python:

    5. Пример класса
    :
        key = "Лучшие времена."
    х = пример
    x.key = "Худшие времена."
    у = пример ()
    печать (y.key)
    > Худшие времена. 

    Почему y , новый объект примера , имеет тот же ключ, что и x , несмотря на то, что, казалось бы, только изменение атрибута в пределах x ? Решение

    1. Добавить метод в geographyStudent class в приведенном выше примере, чтобы напечатать «Удачно», если учащийся получил общую оценку больше или равную 65, или «Незачет» в противном случае. Решение

    Решения

    1. Ниже приведена одна такая реализация.

     класс DoubleLLElement:
    защита __init__(сам):
    self.key = Нет
    self.next = Нет
    self.prev = Нет
    
    класс DoubleLinkedList:
    защита __init__(сам):
    self.root = Нет
    DLL = дважды связанный список ()
    x = Двойной LLElement ()
    DLL.корень = х
    x.key = "Первый элемент"
    печать (DLL.root.key)
    > «Первый элемент» 

    2. Этот пример мотивирует использование наследования:

     класс Ученик:
    школа = "Пример High"
    class geographyStudent(Student): # Здесь вызывается наследование
    def __init__(self, input): #Инициализация каждого атрибута оценки
    self.name = ввод["Имя"]
    self.homework = ввод["HW"]
    self.project1 = ввод["P1"]
    self.midterm = ввод ["M"]
    self.project2 = ввод["P2"]
    self.final = ввод["F"]
    Def finalGrade (я):
    self.grade = (self.homework*0.2
    + селф.проект1*0.1
    + самостоятельная среднесрочная*0,2
    + селф.проект2*0.1
    + сам.финал*0.4)
    возврат (самооценка)
    студенты = []
    for s in geographyClass: # Предполагается, что список словарей в приведенном выше примере существует
    student. append(географияСтудент(ы))
    печать (студенты [1]. школа)
    > Пример Высокий 

    3. Сами списки слишком длинные, чтобы печатать их здесь, но каждый из них можно распечатать с помощью:

    .
     print(dir(True)) # логическое значение
    print(dir(1)) # Целое число
    print(dir(1.0)) # Число с плавающей запятой 

    4. Причина в том, что переменная x ошибочно указывала на конструктор класса, а не на объект, созданный конструктором. Поскольку x указывает на конструктор, ключ атрибута в конструкторе был изменен, и следующие экземпляры объекта класса содержат измененные ключ значение по умолчанию. Важно помнить разницу между объектами класса и конструкторами объектов класса, а также то, как создаются экземпляры объектов.

    5. Мы можем просто добавить еще один метод, который использует существующий метод класса :

     класс географияСтудент(Студент):
    def __init__(я, ввод):
    self. name = ввод["Имя"]
    self.homework = ввод["HW"]
    self.project1 = ввод["P1"]
    self.midterm = ввод ["M"]
    self.project2 = ввод["P2"]
    self.final = ввод["F"]
    Def finalGrade (я):
    self.grade = (self.homework*0.2
    + селф.проект1*0.1
    + самостоятельная среднесрочная*0,2
    + селф.проект2*0.1
    + сам.финал*0.4)
    возврат (самооценка)
    Def PassFail (я):
    оценка = self.finalGrade()
    если оценка >= 65,0:
    Возврат("Пройдено")
    еще:
    Возврат("Неудачно")
    студенты = []
    for s in geographyClass: # Предполагается, что список словарей в приведенном выше примере существует
    student.append(географияСтудент(ы))
    печать (студенты [1].finalGrade())
    > 76,5
    печать (студенты [1]. PassFail ())
    > пройти 

    Этот бесплатный учебник был вам полезен? Поделитесь этой статьей с друзьями, одноклассниками и коллегами в Facebook и Twitter! Когда вы распространяете информацию в социальных сетях, вы помогаете нам расти, чтобы мы могли продолжать предоставлять бесплатные учебные пособия, подобные этому, в течение многих лет.

    1. Функция dir фактически обращается к методу __dir__ объекта для получения необходимой информации.