Классы — Python documentation

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

  • Объект — экземпляр, созданный на основе шаблона.

  • Атрибут — поле, хранящее значение. Содержит свойства объекта.

  • Метод — функция, связанная с классом. Описывает поведение или действия объекта.

Пример класса — автомобили, его атрибутами будут: цвет, марка автомобиля, регистрационный номер.

Методами могут быть: ехать прямо, повернуть, остановиться.

Объектом класса “Автомобили” может быть конкретный автомобиль, например, Renault Logan белого цвета с номером М123РТ.

Для чего нужны классы?

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

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

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

Посмотреть слайды.

Синтаксис и правила создания классов

Для создания класса используется конструкция class ClassName. Согласно договорённостям имя класса всегда пишется с большой буквы.

Каждый класс должен содержать метод __init__ — с помощью этого метода создаётся объект класса. В этом методе инициализируются атрибуты класса:

class Person:  # Объявления класса
    def __init__(self, name, age): # Метод инициализации
        self.age = age   # Установка значений атрибутов
        self.name = name

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

Название

Применение

__init__

Инициализация объекта

__str__

Преобразование к строке str(obj)

__eq__

Проверка на равенство ==

__getitem__

Оператор доступа к элементам |

some_dict[‘item’] |

Пример:

class Person:  # Объявления класса
    def __init__(self, name, age): # Метод инициализации
        self.
age = age # Установка значений атрибутов self.name = name def __str__(self): return f"{self.name} is {self.age} years old" person = Person('John', 20) # Создание экземпляра person.name = 'James' # Установка значения атрибута print(person)

Задачи

  1. Создать класс, описывающий человека. Должны быть поля для имени, фамилии и возраста. Создать экземпляр и вывести информацию о человеке.

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

    str над экземпляром.

  3. Добавить метод greet, вызов которого будет выводить в консоль информацию о человеке в формате "Привет! Меня зовут Петров Василий, мне 12 лет".

  4. Добавить атрибут grades, в котором будет храниться список оценок. Создать список учеников, заполняя оценки случайными числами, и вывести информацию о них в порядке убывания среднего балла. Заполнение оценок и подсчёт среднего балла вынести в отдельные методы.

  5. Создайте класс прямоугольник — Rectangle. Метод

    __init__ принимает две точки — левый верхний и правый нижний угол. Каждая точка представлена экземпляром класса Point. Реализуйте методы вычисления площади и периметра прямоугольника.

  6. Добавьте в класс Rectangle метод has_point. Метод принимает точку на плоскости и возвращает True, если точка находится внутри прямоугольника и False в противном случае.

  7. Создайте класс фигура — Figure. Метод __init__ принимает число — количество строительных блоков фигуры. Каждый объект будет состоять из заданного количества строительных блоков. У класса должен быть метод print_figure, который печатает фигуру. С использованием этого класса реализуйте программу, которая будет “строить стену” из случайного количества строительных блоков.

Пример:

Строительный блок:
         _
        |_|
Вывод:
          _  _  _
         |_||_||_|
          _  _
         |_||_|
          _  _  _  _
         |_||_||_||_|

Объект класса и конструктор класса в 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 — изучайте на примерах

Классы и объекты — это два основных аспекта объектно-ориентированного программирования.

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

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

Знаете ли вы?

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

Однако Python скрывает механизм объекта с помощью специального синтаксиса.

Например, когда вы вводите num = 42 , Python фактически создает новый объект типа integer со значением 42 и присваивает его ссылке имя num .

Создайте класс

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

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

Вот самый простой возможный класс (пустой):

 класс Автомобиль:
    pass 

Здесь оператор pass используется для указания того, что этот класс пуст.

Метод __init__()

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

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

 класс Автомобиль:
    
    # инициализатор
    защита __init__(сам):
        pass 

Когда вы определяете __init__() в определении класса, его первым параметром должно быть self .

Параметр self

Параметр self относится к самому индивидуальному объекту. Он используется для получения или установки атрибутов конкретного экземпляра.

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

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

Атрибуты

Каждый класс, который вы пишете на Python, имеет две основные функции: атрибуты и методы .

Атрибуты — это отдельные вещи, которые отличают один объект от другого. Они определяют внешний вид, состояние или другие качества этого объекта.

В нашем случае класс «Автомобиль» может иметь следующие атрибуты:

  • Стиль: седан, внедорожник, купе
  • Цвет: серебристый, черный, белый
  • Колеса: четыре

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

Существует два типа атрибутов: Атрибуты экземпляра и Атрибуты класса .

Атрибут экземпляра

Атрибут экземпляра — это переменная, уникальная для каждого объекта (экземпляра). Каждый объект этого класса имеет свою собственную копию этой переменной. Любые изменения, внесенные в переменную, не отражаются на других объектах этого класса.

В случае нашего класса Car() каждая машина имеет определенный цвет и стиль.

 # Класс с двумя атрибутами экземпляра
Класс Автомобиль:
    # инициализатор с атрибутами экземпляра
    def __init__(я, цвет, стиль):
        self.color = цвет
        self.style = style 

Атрибут класса

Атрибут класса — это переменная, одинаковая для всех объектов. И есть только одна копия этой переменной, которая является общей для всех объектов. Любые изменения, внесенные в эту переменную, отразятся на всех других объектах.

В случае нашего класса Car() каждая машина имеет 4 колеса.

 # Класс с одним атрибутом класса
Класс Автомобиль:
    # атрибут класса
    колеса = 4
    # инициализатор с атрибутами экземпляра
    def __init__(я, цвет, стиль):
        self. color = цвет
        self.style = style 

Таким образом, хотя каждая машина имеет уникальный стиль и цвет, каждая машина будет иметь 4 колеса.

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

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

 # Создать объект из класса «Автомобиль», передав стиль и цвет
Класс Автомобиль:
    # атрибут класса
    колеса = 4
    # инициализатор с атрибутами экземпляра
    def __init__(я, цвет, стиль):
        self.color = цвет
        селф.стиль = стиль
c = Car('Sedan', 'Black') 

Здесь мы создали новый объект из класса Car, передав строки для параметров стиля и цвета. Но мы не прошли аргумент self .

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

Доступ и изменение атрибутов

Атрибуты экземпляра доступны и назначаются с помощью точки . Обозначение .

 # Доступ и изменение атрибутов объекта
Класс Автомобиль:
    # атрибут класса
    колеса = 4
    # инициализатор с атрибутами экземпляра
    def __init__(я, цвет, стиль):
        self.color = цвет
        селф.стиль = стиль
c = Автомобиль('Черный', 'Седан')
# Доступ к атрибутам
печать (c.style)
# Печатает седан
печать (ц.цвет)
# Печатает черный
# Изменить атрибут
c.style = 'внедорожник'
печать (c.style)
# Печатает внедорожник 

Методы

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

В нашем случае класс ‘Car’ может иметь следующие методы:

  • Изменить цвет
  • Запустить двигатель
  • Остановить двигатель
  • Переключить передачу и методы класса.

    Методы экземпляра работают с экземпляром класса; тогда как методы класса работают с самим классом.

    Методы экземпляра

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

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

    • showDescription() метод: вывести текущие значения всех атрибутов экземпляра
    • changeColor() метод: изменить значение атрибута «цвет»
     класс Автомобиль:
        # атрибут класса
        колеса = 4
        # атрибуты инициализатора/экземпляра
        def __init__(я, цвет, стиль):
            self.color = цвет
            селф.стиль = стиль
        # способ 1
        деф шоуОписание(я):
            print("Этот автомобиль", self.color, self.style)
        # способ 2
        def changeColor (я, цвет):
            self.color = цвет
    c = Автомобиль('Черный', 'Седан')
    # метод вызова 1
    c.showDescription()
    # Печатает Эта машина — черный седан
    # вызвать метод 2 и установить цвет
    c.changeColor('Белый')
    c.showDescription()
    # Печатает Эта машина — белый седан 

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

    Чтобы удалить любой атрибут объекта, используйте ключевое слово del.

     del c.color 

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

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

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

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

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

    Из этого руководства вы узнаете, как:

    • Создавать классы и объекты в Python и работать с ними
    • Определение атрибутов и методов экземпляра
    • Определить переменные и методы класса
    • Использовать методы класса в качестве конструкторов
    • Определить статические методы

    Как создавать классы и объекты в Python

    Python изначально поддерживает объектно-ориентированное программирование, и все создаваемые вами переменные являются объектами. Вы можете запустить Python REPL и выполнить следующую строку кода: она вызывает функцию type() с py_num в качестве аргумента. Вывод читает означает, что py_num является объектом целочисленного класса.

     >>> py_num = 8
    >>> тип (py_num)
     

    Вы можете проверить это еще для нескольких встроенных типов данных.

     >>> py_str = "Строка Python"
    >>> тип (py_str)
    <класс 'ул'>
    >>> py_list = [2,4,9]
    >>> тип (py_list)
     

    Как и все современные языки программирования, Python позволяет создавать собственные классы. А класс — это шаблон или план, из которого можно создать объектов класса, также называемых экземплярами .

    Чтобы создать класс, вы можете использовать ключевое слово class , за которым следует имя класса: class ClassName . По соглашению имена классов указываются в регистре языка Паскаль, где первая буква каждого слова в имени переменной пишется с большой буквы.

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

    Вы можете скачать код и следовать ему.

    Весь приведенный ниже код находится в файле main.py .

     класс Студент:
        передайте # заполнитель для кода, который мы скоро напишем! 

    После того, как вы создали класс, вы можете создать объект, вызвав класс, как если бы он был функцией.

     student_1 = Student() 

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

    • Вызов функции type() с именем объекта в качестве аргумента.

    • Вызов функции isinstance() . isinstance(,) возвращает True , если является экземпляром класса ; в противном случае возвращается False .

     печать (тип (student_1))
    print(isinstance(student_1,Student)) 
     # Вывод
    <класс '__main__.Студент'>
    Правда 

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

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

    После создания экземпляра вы можете определить атрибуты, используя <имя_объекта>.<имя_атрибута> = <значение> .

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

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

    __init__

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

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

    Использование self в качестве первого параметра является рекомендуемой практикой в ​​соответствии с Руководством по стилю PEP 8 и не является строгим требованием.

     класс Студент:
        def __init__(я,имя,фамилия,обучение):
            self.first_name = первое_имя
            self.last_name = фамилия
            self.tuition = tuition 

    Всякий раз, когда вы создаете экземпляр класса Student , метод __init__ делает следующее:

    • Он автоматически принимает экземпляр в качестве первого аргумента (обозначается сам ). В этом примере экземпляр обозначает конкретный объект студента.
    • Присваивает значения параметров first_name , last_name и tuition атрибутам экземпляра first_name , last_name и tuition конкретного экземпляра.

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

     класс Студент:
        def __init__(self,fname,lname,tuition_amt):
            self.first_name = fname
            self.last_name = имя
            self.tuition = tuition_amt 

    Подводя итог тому, что мы уже узнали: класс Student служит шаблоном — с атрибутами first_name , last_name и tuition — из которых мы можем создавать объекты ученика каждый имеющие собственные имена и фамилии и соответствующую плату за обучение.

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


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

     student_1 = Студент («Джейн», «Смит», 20000)
    student_2 = Student('John','Doe',15000) 

    Как определить и вызвать методы экземпляра

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

    Вернемся к примеру класса Student .

    Учитывая атрибуты first_name и last_name , мы можем определить методы, которые используют эти атрибуты и возвращают полное имя и адрес электронной почты для каждого объекта студента. Мы называем эти методы get_full_name() и get_email() соответственно. Помните, что все методы экземпляра принимают экземпляр ( self ) в качестве первого аргумента.

     класс Студент:
        def __init__(я,имя,фамилия,обучение):
            self.first_name = первое_имя
            self. last_name = фамилия
            самообучение = обучение
        защита get_full_name (я):
            вернуть f"{self.first_name} {self.last_name}"
        защита get_email (я):
            return f"{self.first_name}.{self.last_name}@school.edu" 

    Чтобы вызвать метод экземпляра, который вы можете использовать, . . Вы также можете вызвать метод экземпляра, используя класс с синтаксисом: <имя_класса>.<метод>(<имя_экземпляра>) . Несмотря на многословность, этот метод помогает понять, как экземпляр передается в качестве первого аргумента.

     # вызов метода экземпляра на экземпляре
    печать (student_1.get_email())
    # вызов метода экземпляра с использованием класса
    печать (Студент.get_email (студент_2)) 
     # Выход
    Джейн.Смит@school.edu
    [email protected] 

    Что такое переменные класса и как их использовать?

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

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

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

    Инициализация и доступ к переменным класса

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

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

     класс Студент:
        академический год = '2022-23'
        количество_студентов = 0
        def __init__(я,имя,фамилия,обучение):
            self. first_name = первое_имя
            self.last_name = фамилия
            самообучение = обучение
            Студент.num_students +=1
        защита get_full_name (я):
            вернуть f"{self.first_name} {self.last_name}"
        защита get_email (я):
            return f"{self.first_name}.{self.last_name}@school.edu" 

    Вы можете получить доступ к переменным класса, используя синтаксис: ClassName.var_name .

     student_1 = Студент («Джейн», «Смит», 20000)
    student_2 = Студент («Джон», «Доу», 15000)
    печать(Студент.академический_год)
    print(Student.num_students) 

    Мы создали два объекта student, поэтому значение переменной класса num_students теперь равно 2.

     # Вывод
    2022-23
    2 

    Как использовать методы класса в Python

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

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

    Чтобы преобразовать метод экземпляра в метод класса, вы можете использовать декоратор @classmethod в Python. По соглашению первый аргумент в методах класса — cls , точно так же, как первый аргумент в методах экземпляра — self .

     @метод класса
        def set_fee_waiver (cls,fee_waiver):
            cls.fee_waiver = Fee_waiver 

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

     по определению apply_fee_waiver (сам):
            self. tuition -= self.tuition*Student.fee_waiver
            return self.tuition 

    Давайте установим fee_waiver и применим освобождение от платы для student_1 .

     Student.set_fee_waiver(0.1)
    print(student_1.apply_fee_waiver()) 
     # Вывод
    # 0.1*плата за обучение отменена
    18000.0 

    Декораторы в Python: обзор

    Начнем с примера.

     определение добавить (х, у):
      вернуть х + у 

    Здесь add() — это функция, которая принимает два числа и возвращает их сумму.

    Допустим, мы хотели бы изменить эту функцию, удвоив каждый из аргументов перед сложением. Мы могли бы изменить оператор return следующим образом: return 2*x + 2*y , но что, если вы больше не хотите удваивать аргументы? В этом случае вам придется еще раз изменить определение функции. Входят декораторы.

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

    Прочтите приведенный ниже фрагмент кода.

     по умолчанию double_xy(f):
      обертка защиты (x, y):
        вернуть f(2*x,2*y)
      возвратная упаковка 

    Давайте разберем определение double_xy() .

    • Функция double_xy() принимает в качестве аргумента функцию f .
    • В теле функции мы определяем функцию wrapper() с параметрами x и y .
    • wrapper() возвращает функцию f , вызываемую с 2*x и 2*y в качестве аргументов.
    • Функция double_xy() возвращает внутреннюю функция обертки() .

    Затем вы можете вызвать функцию double_xy() с добавить в качестве аргумента и присвоить его (снова) добавить — точно так же, как вы вызываете функцию и присваиваете ее возвращаемое значение переменной.

    Теперь, когда вы вызываете add() со значениями x и y , она возвращает сумму 2*x и 2*y .

     добавить = double_xy(добавить)
    добавить(1,2) #6 

    Вместо приведенного выше подробного синтаксиса у вас есть краткий синтаксис. Просто добавьте @double_xy над определением функции add() , как показано ниже.

     @double_xy
    определить добавить (х, у):
      вернуть х + у
    добавить(1,2) #6 

    Следовательно, функция double_xy() украшает функцию add() , чтобы иметь свойство удваивать аргументы и вычислять их сумму.

    На данный момент у нас есть следующий код в файле main.py .

     класс Студент:
       #переменные класса
        академический год = '2022-23'
        количество_студентов = 0
        def __init__(я,имя,фамилия,обучение):
            self.first_name = первое_имя
            self.last_name = фамилия
            самообучение = обучение
            Студент. num_students +=1
        защита get_full_name (я):
            вернуть f"{self.first_name} {self.last_name}"
        защита get_email (я):
            вернуть f"{self.first_name}.{self.last_name}@school.edu"
        
        @классметод
        def set_fee_waiver (cls,fee_waiver):
            cls.fee_waiver = плата_отказ
        
        def apply_fee_waiver (сам):
            self.tuition -= self.tuition*Student.fee_waiver
            вернуться самообучение 

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

    Как использовать методы класса в качестве конструкторов

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

     student_tuple = ("Джейн", "Смит", 20000)
    first_name,last_name,tuition = ('Джейн','Смит',20000)
    student_1 = Студент(имя,фамилия,плата за обучение) 

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

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

     @метод класса
        защита from_tuple (cls, student_tuple):
            first_name, last_name, tuition = student_tuple
            вернуть cls(first_name,last_name,tuition) 

    Теперь вы можете создавать объекты учеников из кортежей, используя метод from_tuple() в качестве конструктора.

     student_tuple_1 = («Джейн», «Смит», 20000)
    student_1 = Student.from_tuple (student_tuple_1)
    student_tuple_2 = ('Джон','Доу',25000)
    student_2 = Student.from_tuple(student_tuple_2) 

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

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

    Например, в классе Студент можно определить метод is_fall() , который принимает дату и проверяет, является ли текущий семестр осенним.

    Для работы с датами давайте импортируем класс date из встроенного Python datetime 9Модуль 0018.

     from datetime date import date 

    Чтобы определить статический метод, вы можете использовать декоратор @staticmethod . Предполагая, что месяцы сентябрь, октябрь и ноябрь соответствуют осени, мы проверяем, находится ли атрибут месяца даты, переданный в качестве аргумента функции is_fall() , в списке [9,10,11].

    Давайте добавим в класс следующее определение is_fall() .

     @статический метод
        защита is_fall (дата):
            если дата.месяц в [9,10,11]:
                print("Да, идет осенний семестр.")
            еще:
                print("Не осенний семестр") 

    Несмотря на то, что статический метод не привязан к классу или экземпляру класса, он все еще присутствует в пространстве имен класса Student . Вы можете вызвать статический метод точно так же, как любой метод класса в области видимости, используя синтаксис: ClassName.static_method() . Давайте вызовем is_fall() с сегодняшней датой в качестве аргумента, а в 2022 году еще не осень.0003

     сегодня = дата.сегодня()
    Student.is_fall(сегодня) 
     # Вывод:
    Не осенний семестр 

    Собрав все вместе, мы имеем следующий код в файле main.py .

     с даты импорта даты и времени
    Ученик класса:
        академический год = '2022-23'
        количество_студентов = 0
        def __init__(я,имя,фамилия,обучение):
            self.first_name = первое_имя
            self.last_name = фамилия
            самообучение = обучение
            Студент.num_students +=1
        защита get_full_name (я):
            вернуть f"{self.first_name} {self.last_name}"
        защита get_email (я):
            вернуть f"{self.first_name}.{self.last_name}@school.edu"
        
        @классметод
        def set_fee_waiver (cls,fee_waiver):
            cls. fee_waiver = плата_отказ
        
        def apply_fee_waiver (сам):
            self.tuition -= self.tuition*Student.fee_waiver
            вернуться самообучение
     
        # метод класса как конструктор
        @классметод
        защита from_tuple (cls, student_tuple):
            first_name, last_name, tuition = student_tuple
            вернуть cls(имя,фамилия,обучение)
        @статический метод
        защита is_fall (дата):
            если дата.месяц в [9,10,11]:
                print("Да, идет осенний семестр.")
            еще:
                print("Не осенний семестр") 

    Заключение

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

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