跳转到主要内容
模块 7 · 第 3 课(共 4)课程中的27/36~12 min
模块课程(3/4)

特殊方法(dunder)

特殊方法(称为 dunder 方法,因为它们开始和结束 带双下划线:__name__) 是让您的对象 与语言集成:文本表示,与 == 比较, 支持 len()、in、运算符等。

您已经使用过一个:__init__。

__str__ 和 __repr__

它们控制 print() 和 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

如果仅定义 __repr__,Python 也会使用它作为后备 __str__。

__eq__:重新定义==

默认情况下 a == b 比较对象的 标识符 (is),而不是 他们的内容。为了进行结构比较,定义 __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

当类型返回 NotImplemented (一个特殊关键字,而不是 False!) 不可比较是正确的做法:Python 将尝试使用 其他操作数的 __eq__。

__len__:支持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)

通过定义 __len__,您还可以免费获得 boolean:一个对象 与 len() == 0 变得虚假。

其他有用的dunders(概述)

  • __add__(self, other) → 重新定义 +
  • __lt__、__le__、__gt__、__ge__ → 比较运算符
  • __contains__(self, item) → 支持 item in self
  • __iter__ + __next__ → 使对象可迭代
  • __getitem__(self, key) → 支持 self[key]
  • __hash__ → 必须是字典键/集合元素

轮到你了

锻炼#python.m7.l3.e1
尝试:0加载中...

使用 __init__(self, amount,currency) 和返回 `f'{amount} {currency}'` 的 __str__ 定义 `Money`。创建 `s = Money(42, 'EUR')` 并评估 `str(s)`。

正在加载编辑器...
显示提示

__str__ 中的 f 字符串。

3 次尝试后可用的解决方案

复习练习

锻炼#python.m7.l3.e2
尝试:0加载中...

根据 (a, b) 的结构比较,使用 __init__(self, a, b) 和 __eq__ 定义“Pair”。评估“Pair(1, 2) == Pair(1, 2)”。

正在加载编辑器...
显示提示

比较元组 (self.a, self.b) == (other.a, other.b)。

3 次尝试后可用的解决方案

额外的挑战

锻炼#python.m7.l3.e3
尝试:0加载中...

定义一个类“Book”,其构造函数采用“title”和“author”。定义特殊方法“__str__(self)”,使其返回字符串“Title by Author”(例如“1984 by George Orwell”)。实例化一本书并评估“str(book)”。

正在加载编辑器...
显示提示

在 def __str__(self): 中使用 f"{self.title} by {self.author}" 。

3 次尝试后可用的解决方案