模块课程(3/4)
特殊方法(dunder)
特殊方法(称为 dunder 方法,因为它们开始和结束
带双下划线:__name__) 是让您的对象
与语言集成:文本表示,与 == 比较,
支持 len()、in、运算符等。
您已经使用过一个:__init__。
__str__ 和 __repr__
它们控制 print() 和 REPL 中出现的内容。
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__:
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()
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__→ 必须是字典键/集合元素
轮到你了
使用 __init__(self, amount,currency) 和返回 `f'{amount} {currency}'` 的 __str__ 定义 `Money`。创建 `s = Money(42, 'EUR')` 并评估 `str(s)`。
显示提示
__str__ 中的 f 字符串。
3 次尝试后可用的解决方案
复习练习
根据 (a, b) 的结构比较,使用 __init__(self, a, b) 和 __eq__ 定义“Pair”。评估“Pair(1, 2) == Pair(1, 2)”。
显示提示
比较元组 (self.a, self.b) == (other.a, other.b)。
3 次尝试后可用的解决方案
额外的挑战
定义一个类“Book”,其构造函数采用“title”和“author”。定义特殊方法“__str__(self)”,使其返回字符串“Title by Author”(例如“1984 by George Orwell”)。实例化一本书并评估“str(book)”。
显示提示
在 def __str__(self): 中使用 f"{self.title} by {self.author}" 。
3 次尝试后可用的解决方案