Методы Python: экземплярные, классовые, статические и специальные
Основы методов объектов в Python
Метод - это функция, определённая внутри класса и предназначенная для работы с данными объекта или самого класса. В Python существуют разные виды методов, каждый из которых решает свою задачу. Ниже рассматривается основной подход (метод экземпляра) и несколько альтернативных вариантов.
Как определить метод, который обращается к атрибутам конкретного объекта?
Самый распространённый тип - метод экземпляра. Он всегда принимает первым параметром self - ссылку на текущий объект. Через self можно читать и изменять атрибуты экземпляра.
class Person:
def __init__(self, name):
self.name = name
def greet(self):
return f'Привет, меня зовут {self.name}'
p = Person('Анна')
print(p.greet())атрибуты класса python (атрибуты классов и объектов в python)
Привет, меня зовут Анна
библиотека классов python (библиотека классов в python)
Типичная ошибка: забыть указать self в определении метода. Если написать def greet(): ..., Python передаст объект как первый аргумент, что вызовет ошибку «missing 1 required positional argument».
Решение: всегда добавлять self первым параметром, даже если этот параметр не используется внутри метода.
Как создать метод, работающий с классом в целом, а не с его экземпляром?
Для этого используется декоратор @classmethod. Первый параметр такого метода - cls (ссылка на класс). Методы класса часто применяются для альтернативных конструкторов или изменения состояния, общего для всех экземпляров.
class Counter:
total = 0
@classmethod
def increment(cls, amount=1):
cls.total += amount
Counter.increment()
Counter.increment(5)
print(Counter.total)метод объекта python (методы объектов в python)
6
Python структура объекта (структура объекта в python)
Типичная ошибка: использование self вместо cls. Это не приведёт к синтаксической ошибке, но метод потеряет связь с классом.
Решение: для методов, которые не нуждаются в информации об объекте, но работают с атрибутами класса, выбирать @classmethod.
Как определить утилитарный метод внутри класса, не требующий доступа ни к self, ни к cls?
Такой метод помечается декоратором @staticmethod. Он ведёт себя как обычная функция, но находится в пространстве имён класса. Статические методы удобны для вспомогательных вычислений, связанных с классом по смыслу.
class MathUtils:
@staticmethod
def add(a, b):
return a + b
print(MathUtils.add(3, 4))Python создание объектов (создание объектов в python)
7
Self object python (объект self в python)
Типичная ошибка: попытка обратиться к self или cls внутри статического метода. Это вызовет ошибку, так как эти переменные не определены.
Решение: если методу нужны данные класса или экземпляра, следует использовать метод экземпляра или класса, а не статический.
Как переопределить стандартное поведение объектов (строковое представление, инициализация)?
В Python есть специальные методы (dunder-методы), заключённые в двойные подчёркивания. Они позволяют задать, как объект ведёт себя в различных контекстах: инициализация __init__, строковое представление __str__ и __repr__, сравнение __eq__ и другие.
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f'"{self.title}" - {self.author}'
b = Book('Мастер и Маргарита', 'Булгаков')
print(b)Object attribute python (атрибуты объекта в python)
"Мастер и Маргарита" - Булгаков
Типичная ошибка: неверное количество аргументов в специальном методе. Например, __init__ должен иметь хотя бы self, а при создании объекта передаются аргументы после self.
Решение: сверяться с документацией по нужному методу и чётко прописывать параметры.
Расширенные примеры методов объектов
Здесь представлены более тонкие возможности, которые часто упускаются из виду, но добавляют гибкости коду.
Методы как свойства (property)
Декоратор @property позволяет вызывать метод без круглых скобок, как обычный атрибут. Это полезно для вычисляемых значений:
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def area(self):
return 3.14159 * self._radius ** 2
c = Circle(5)
print(c.area)78.53975
Перегрузка операторов (методы __add__, __eq__ и др.)
Позволяет использовать объекты с операторами +, ==, [] и т.д. Например, векторное сложение:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return f'Vector({self.x}, {self.y})'
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)Vector(4, 6)
Вызов объекта как функции (__call__)
Метод __call__ позволяет экземпляру вести себя как функция. Это удобно для замыканий или объектов-декораторов:
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x):
return x * self.factor
double = Multiplier(2)
print(double(5))10
Методы для цепочек вызовов (fluent interface)
Возвращая self из метода, можно строить цепочки вызовов:
class Query:
def __init__(self):
self._conditions = []
def where(self, condition):
self._conditions.append(condition)
return self
def order_by(self, field):
self._order = field
return self
def execute(self):
return f'SELECT * FROM table WHERE {" AND ".join(self._conditions)} ORDER BY {self._order}'
q = Query().where('age > 18').where('status = active').order_by('name')
print(q.execute())SELECT * FROM table WHERE age > 18 AND status = active ORDER BY name
Методы с динамическим именем (getattr)
Функция getattr позволяет вызывать метод по строковому имени. Это бывает нужно при работе с плагинами или командами:
class Actions:
def say_hello(self):
return 'Hello!'
def say_goodbye(self):
return 'Goodbye!'
a = Actions()
cmd = 'say_hello'
method = getattr(a, cmd, None)
if method:
print(method())Hello!
Абстрактные методы (abc)
Модуль abc позволяет объявить метод, который должен быть переопределён в подклассе. Это основа для шаблонного проектирования:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
s = Square(4)
print(s.area())16
Методы как объекты первого класса (привязка и отвязка)
Метод можно сохранить в переменную и передать как аргумент. При этом контекст объекта сохраняется, если метод извлекается из экземпляра:
class Greeter:
def __init__(self, name):
self.name = name
def greet(self):
return f'Привет, {self.name}'
g = Greeter('Мир')
bound_method = g.greet
print(bound_method())Привет, Мир
Можно также вызвать метод через класс, передав экземпляр явно:
unbound_method = Greeter.greet
print(unbound_method(g))Привет, Мир