Метод __init__ и self
Метод init и self
Мы уже видели __init__ и self в предыдущих уроках — пора разобрать их детально. Эти два элемента — основа работы с классами. Понять их означает понять, как объекты «оживают» при создании.
self — ссылка на текущий объект
self — это первый параметр любого метода экземпляра. Он содержит ссылку на конкретный объект, с которым работает метод. Имя self — конвенция (можно написать this или что угодно), но никогда так не делайте: self ожидают все Python-разработчики.
class Counter:
def increment(self):
self.value += 1 # self — это конкретный счётчик
c1 = Counter()
c1.value = 0
c2 = Counter()
c2.value = 0
c1.increment()
c1.increment()
c2.increment()
print(c1.value) # 2
print(c2.value) # 1 — разные объекты, независимые значения
При вызове c1.increment() Python автоматически передаёт c1 как self. Это эквивалентно явному вызову Counter.increment(c1).
init — инициализатор объекта
__init__ — специальный метод, который Python вызывает автоматически сразу после создания объекта. Его задача — инициализировать атрибуты и привести объект в рабочее состояние:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Привет, я {self.name}, мне {self.age} лет"
alice = Person("Алиса", 25) # __init__ вызывается здесь
print(alice.greet())
# Привет, я Алиса, мне 25 лет
Аргументы name и age переданы в Person("Алиса", 25) попадают в __init__ как параметры (кроме self, который Python передаёт сам).
init с проверкой значений
__init__ — отличное место для валидации входных данных:
class Temperature:
ABSOLUTE_ZERO = -273.15
def __init__(self, celsius):
if celsius < self.ABSOLUTE_ZERO:
raise ValueError(
f"Температура {celsius}°C ниже абсолютного нуля ({self.ABSOLUTE_ZERO}°C)"
)
self.celsius = celsius
def to_fahrenheit(self):
return self.celsius * 9/5 + 32
def to_kelvin(self):
return self.celsius - self.ABSOLUTE_ZERO
t = Temperature(100)
print(t.to_fahrenheit()) # 212.0
print(t.to_kelvin()) # 373.15
# Temperature(-300) # ValueError: ниже абсолютного нуля
Значения по умолчанию в init
Как и обычные функции, __init__ поддерживает значения по умолчанию:
class Config:
def __init__(self, host="localhost", port=8080, debug=False):
self.host = host
self.port = port
self.debug = debug
def address(self):
return f"{self.host}:{self.port}"
default_config = Config()
prod_config = Config("api.example.com", 443)
dev_config = Config(debug=True)
print(default_config.address()) # localhost:8080
print(prod_config.address()) # api.example.com:443
print(dev_config.debug) # True
init не возвращает значение
Важная особенность: __init__ не должен возвращать ничего, кроме None. Если напишете return value, Python выбросит TypeError. Объект создаётся до вызова __init__ — инициализатор его только заполняет.
Практический пример: класс Card
class Card:
SUITS = ("♠", "♥", "♦", "♣")
RANKS = ("2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A")
def __init__(self, rank, suit):
if rank not in self.RANKS:
raise ValueError(f"Неверный ранг: {rank}")
if suit not in self.SUITS:
raise ValueError(f"Неверная масть: {suit}")
self.rank = rank
self.suit = suit
def __str__(self):
return f"{self.rank}{self.suit}"
card = Card("A", "♠")
print(card) # A♠
Итог
self— первый параметр любого метода; ссылка на конкретный экземпляр.__init__(self, ...)вызывается автоматически при создании объекта черезClassName(...).- Внутри
__init__назначайте атрибуты:self.attr = value. - Проверяйте данные в
__init__и выбрасывайте исключения при невалидных значениях. __init__не возвращает значение (толькоNone).
В следующем уроке изучим наследование — механизм создания новых классов на основе существующих.