W3docs

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

Узнайте, как работают классы и объекты Python: определение классов, __init__, создание экземпляров, атрибуты, методы и наследование.

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

В этой главе рассматривается:

  • Что такое классы и объекты и почему они важны
  • Определение класса с __init__, атрибутами экземпляра и методами
  • Атрибуты класса в сравнении с атрибутами экземпляра
  • Создание и использование объектов
  • Изменение и удаление атрибутов
  • Проверка типов объектов с помощью isinstance()
  • Первое знакомство с наследованием

Для более глубокого изучения наследования смотрите Python Inheritance. Более сложные паттерны ООП описаны в Python Abstract Base Classes.

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

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

class Dog:
    pass  # an empty class — valid but not very useful yet

Ключевое слово class, за которым следуют имя и двоеточие, создаёт новый класс. По соглашению имена классов используют CapWords (также называемый PascalCase): MyClass, BankAccount, HttpRequest.

Метод __init__

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

class Dog:
    def __init__(self, name, age):
        self.name = name   # instance attribute
        self.age = age     # instance attribute

Первый параметр всегда self — он ссылается на создаваемый объект. Python передаёт его автоматически; вам никогда не нужно указывать его самостоятельно.

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

ВидОпределяется внутриПринадлежитОбщий?
Атрибут экземпляра__init__ (через self)Каждому объектуНет — у каждого объекта своя копия
Атрибут классаТело класса (вне любого метода)Самому классуДа — все объекты используют одну копию
class Dog:
    species = "Canis familiaris"  # class attribute — shared by all Dogs

    def __init__(self, name, age):
        self.name = name   # instance attribute
        self.age = age     # instance attribute

fido = Dog("Fido", 3)
bella = Dog("Bella", 5)

print(fido.species)    # Canis familiaris
print(bella.species)   # Canis familiaris  (same class attribute)
print(fido.name)       # Fido
print(bella.name)      # Bella             (different instance attributes)

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

Определение методов

Метод — это функция, определённая внутри класса. Как и __init__, он всегда принимает self в качестве первого параметра, чтобы иметь доступ к атрибутам объекта.

class Dog:
    species = "Canis familiaris"

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def bark(self):
        return f"{self.name} says: Woof!"

    def description(self):
        return f"{self.name} is {self.age} years old."

Метод вызывается на объекте через точечную нотацию — Python автоматически передаёт объект как self:

fido = Dog("Fido", 3)
print(fido.bark())          # Fido says: Woof!
print(fido.description())   # Fido is 3 years old.

Метод __str__

Python вызывает __str__, когда вы передаёте объект в print() или str(). Без него вы получаете бесполезный адрес вроде <__main__.Dog object at 0x...>. Определение этого метода значительно упрощает отладку.

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"Dog(name={self.name!r}, age={self.age})"

fido = Dog("Fido", 3)
print(fido)   # Dog(name='Fido', age=3)

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

Создание объекта называется инстанциированием. Вы вызываете класс как функцию, передавая аргументы, которые ожидает __init__ (кроме self):

python— editable, runs on the server

Из одного класса можно создать сколько угодно объектов — каждый из них независим:

class Rectangle:
    def __init__(self, width, height=1):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    def perimeter(self):
        return 2 * (self.width + self.height)

r1 = Rectangle(4, 3)
r2 = Rectangle(5)      # height defaults to 1

print(r1.area())        # 12
print(r1.perimeter())   # 14
print(r2.area())        # 5

Обратите внимание, что height=1 задаёт значение по умолчанию: если второй аргумент не указан, Python автоматически использует 1.

Изменение и удаление атрибутов

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

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 30)
print(p.age)      # 30

p.age = 31        # modify an existing attribute
print(p.age)      # 31

p.email = "[email protected]"   # add a new attribute at runtime
print(p.email)    # [email protected]

del p.email       # delete the attribute
# print(p.email)  # would raise AttributeError

Хотя Python позволяет свободно добавлять атрибуты, чище объявлять все атрибуты внутри __init__, чтобы структура класса была понятна с первого взгляда.

Проверка типов объектов

Используйте isinstance(), чтобы проверить, является ли объект экземпляром определённого класса. Функция возвращает True как для самого класса, так и для любого из его родительских классов:

class Animal:
    pass

class Dog(Animal):
    pass

rex = Dog()
print(isinstance(rex, Dog))     # True
print(isinstance(rex, Animal))  # True  — Dog is a subclass of Animal
print(type(rex) is Dog)         # True
print(type(rex) is Animal)      # False — type() does not climb the hierarchy

В большинстве случаев предпочитайте isinstance() вместо type() is, поскольку первая корректно обрабатывает подклассы.

Первое знакомство с наследованием

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

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"{self.name} makes a sound."

class Dog(Animal):
    def speak(self):                     # override the parent method
        return f"{self.name} says: Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says: Meow!"

dog = Dog("Rex")
cat = Cat("Whiskers")
print(dog.speak())             # Rex says: Woof!
print(cat.speak())             # Whiskers says: Meow!
print(isinstance(dog, Animal)) # True

И Dog, и Cat наследуют __init__ от Animal, поэтому им не нужно повторять его. Они только переопределяют speak(), чтобы задать поведение, специфичное для каждого вида.

Полное описание наследования — включая super(), множественное наследование и порядок разрешения методов — смотрите в Python Inheritance.

Когда следует использовать класс?

Классы наиболее уместны, когда:

  • У вас есть данные и поведение, которые принадлежат вместе (банковский счёт, умеющий пополняться и списывать средства).
  • Вам нужно несколько независимых объектов одного типа (много объектов Dog, каждый с разными именами и возрастом).
  • Вы хотите смоделировать реальные сущности с чёткой идентичностью.

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

Итоги

КонцепцияЧто делает
classОпределяет новый тип
__init__Инициализирует атрибуты экземпляра при создании объекта
selfСсылается на текущий объект внутри метода
Атрибут экземпляраДанные, принадлежащие одному конкретному объекту
Атрибут классаДанные, общие для всех объектов класса
МетодФункция, определённая внутри класса; всегда принимает self
__str__Управляет тем, как print() отображает объект
isinstance()Проверяет, является ли объект экземпляром класса или его подклассов
НаследованиеПозволяет дочернему классу повторно использовать и расширять родительский класс

Практика

Практика
What is the correct way to create a class in Python?
What is the correct way to create a class in Python?
Was this page helpful?