Chuyển đến nội dung chính
Mô-đun 7 · Bài học 3 trong tổng số 427/36 trong khóa học~12 min
Bài học theo mô-đun (3/4)

Các phương pháp đặc biệt (dunder)

Các phương pháp đặc biệt (được gọi là các phương pháp dunder vì chúng bắt đầu và kết thúc với dấu gạch dưới kép: __name__) là những cái móc cho phép các đối tượng của bạn tích hợp với ngôn ngữ: trình bày văn bản, so sánh với ==, hỗ trợ cho len(), in, toán tử, v.v.

Bạn đã sử dụng một tài khoản: __init__.

__str__ và __repr__

Họ kiểm soát những gì xuất hiện với print() và trong REPL.

Python
class Punto:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Punto({self.x}, {self.y})"

    def __str__(self):
        return f"({self.x}, {self.y})"

p = Punto(3, 4)
str(p)        # '(3, 4)'        — per umani
repr(p)       # 'Punto(3, 4)'   — per debugger / dev
print(p)      # '(3, 4)'
p             # Punto(3, 4)     in REPL → repr
[p, p]        # [Punto(3, 4), Punto(3, 4)]   — sempre repr nei contenitori

Nếu bạn chỉ xác định __repr__, Python cũng sử dụng nó làm dự phòng cho __str__.

__eq__: xác định lại ==

Theo mặc định a == b so sánh mã định danh của các đối tượng (is), chứ không phải nội dung của chúng. Để so sánh cấu trúc, hãy xác định __eq__:

Python
class Punto:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __eq__(self, other):
        if not isinstance(other, Punto):
            return NotImplemented
        return (self.x, self.y) == (other.x, other.y)

Punto(1, 2) == Punto(1, 2)    # True
Punto(1, 2) == Punto(3, 4)    # False

Trả về NotImplemented (một từ khóa đặc biệt, không phải False!) khi loại không thể so sánh được là cách làm đúng: Python sau đó sẽ thử với toán hạng khác __eq__.

__len__: hỗ trợ cho len()

Python
class Cesto:
    def __init__(self):
        self.frutti = []

    def __len__(self):
        return len(self.frutti)

c = Cesto()
c.frutti.append("mela")
len(c)        # 1
bool(c)       # True (len > 0)

Bằng cách xác định __len__, bạn cũng nhận được boolean miễn phí: một đối tượng với len() == 0 trở thành giả.

Những điều ngớ ngẩn hữu ích khác (tổng quan)

  • __add__(self, other) → định nghĩa lại +
  • __lt__, __le__, __gt__, __ge__ → toán tử so sánh
  • __contains__(self, item) → hỗ trợ item in self
  • __iter__ + __next__ → làm cho đối tượng có thể lặp lại
  • __getitem__(self, key) → hỗ trợ self[key]
  • __hash__ → bắt buộc phải là khóa chính tả/phần tử tập hợp

Đến lượt bạn

tập thể dục#python.m7.l3.e1
Nỗ lực: 0Đang tải…

Xác định `Tiền` bằng __init__(bản thân, số tiền, tiền tệ) và __str__ trả về `f'{amount} {currency}'`. Tạo `s = Money(42, 'EUR')` và đánh giá `str(s)`.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

chuỗi f trong __str__.

Giải pháp khả dụng sau 3 lần thử

Xem lại bài tập

tập thể dục#python.m7.l3.e2
Nỗ lực: 0Đang tải…

Xác định `Pair` với __init__(self, a, b) và __eq__ dựa trên so sánh cấu trúc của (a, b). Đánh giá `Cặp(1, 2) == Cặp(1, 2)`.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

So sánh các bộ dữ liệu (self.a, self.b) == (other.a, other.b).

Giải pháp khả dụng sau 3 lần thử

Thử thách bổ sung

tập thể dục#python.m7.l3.e3
Nỗ lực: 0Đang tải…

Xác định một lớp \`Book\` với một hàm tạo lấy \`title\` và \`author\`. Xác định phương thức đặc biệt \`__str__(self)\` để nó trả về chuỗi \`"Title by Author"\` (ví dụ \`'1984 by George Orwell'\`). Khởi tạo một cuốn sách và đánh giá \`str(book)\`.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Sử dụng f"{self.title} của {self.author}" bên trong def __str__(self):.

Giải pháp khả dụng sau 3 lần thử