2.21. Методи та атрибути¶
Метод – це функція, визначена всередині класу. Перший параметр – це екземпляр, на якому викликається метод; традиційно він називається self.
2.21.1. Методи екземпляра¶
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def magnitude(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
p = Point(3, 4)
print(p.magnitude())
Виведення:
5.0
Виклик p.magnitude() автоматично передає p як self. Тіла методів читають і оновлюють атрибути через self так само, як функції читають і оновлюють імена через параметри.
2.21.2. Атрибути екземпляра проти атрибутів класу¶
Атрибути, присвоєні self – зазвичай всередині __init__ – належать конкретному екземпляру:
a = Point(1, 2)
b = Point(10, 20)
a.x = 99
print(a.x, b.x) # 99 10
a.x і b.x – це різні сховища; зміна одного не впливає на інше.
Імена, присвоєні в тілі класу, поза будь-яким методом, є спільними для кожного екземпляра класу:
class Counter:
kind = "tally" # class attribute -- shared
def __init__(self):
self.value = 0 # instance attribute -- per instance
a = Counter()
b = Counter()
print(a.kind, b.kind) # tally tally
Атрибути класу живуть у самому класі і є спільними. Атрибути екземпляра живуть у кожному екземплярі.¶
Атрибут класу доступний так само, як атрибут екземпляра (a.kind); Python спочатку шукає на екземплярі, потім у класі. Присвоєння a.kind створило б новий атрибут екземпляра, що затіняє атрибут класу, залишаючи b.kind незміненим.
Використовуйте атрибути класу для констант і типових значень, які однаково повинен бачити кожен екземпляр. Використовуйте атрибути екземпляра для стану, де кожен об’єкт повинен мати власну копію.
2.21.3. __str__ та __repr__¶
Два спеціальні методи керують тим, як відображається екземпляр. __str__ повертає «зручний» рядок, що використовується print(); __repr__ повертає рядок для «розробника», що використовується в REPL та у відображенні контейнерів:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return "(" + str(self.x) + ", " + str(self.y) + ")"
def __repr__(self):
return "Point(" + str(self.x) + ", " + str(self.y) + ")"
p = Point(3, 4)
print(p) # uses __str__
print([p, p]) # uses __repr__ inside the list
Виведення:
(3, 4)
[Point(3, 4), Point(3, 4)]
Якщо визначено лише __repr__, print() звертається до нього – тому одного добре написаного __repr__ зазвичай достатньо. Визначайте __str__ також лише тоді, коли зручна форма має відрізнятися від форми для розробника. Прагніть до такого __repr__, що виглядає як виклик, який відтворить об’єкт; налагодження стає значно простішим, коли надруковані значення однозначні.