Python __format__() 语法
__format__() 是 Python 的一个特殊方法(又称 “魔法方法” 或 “双下划线方法”),它用于定义当使用 format() 函数、f-string 或 str.format() 方法时,如何生成其字符串表示。
语法:
class MyObject:
def __format__(self, format_spec):
# 返回对象的格式化字符串表示
return 'xxx'
说明:
__format__() 方法接收以下 2 个参数。
self(必选):约定俗成的名称,表示类的实例本身。base(可选,默认值:''):是一个字符串,表示格式说明符。例如,在 '{}' 中,format_spec 是空字符串;在 '{:.2f}' 中,format_spec 是 '.2f'。
__format__() 方法必须返回一个字符串。通过实现 __format__() 方法,我们可以控制对象在不同格式化需求下的输出样式,例如指定宽度、精度、对齐方式等。
注意:如果一个类没有定义 __format__() 方法,那么当我们尝试使用 format() 函数、f-string 等转换该类的实例时,它会回退到使用对象的默认字符串表示(通常是 __str__() 或 __repr__() 的结果)。
Python __format__() 摘要
| 属于 | Python 魔法方法 |
|---|---|
| 使用频率 | 高 |
| 官方文档 | 查看 |
| 相关方法 | __str__()、__repr__() |
Python __format__() 示例
接下来,我们通过几个简单的例子来讲解一下 Python __format__() 方法是如何使用的。
示例 1:__format__() 基本用法
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __format__(self, format_spec):
if format_spec == 'coords':
return f'({self.x}, {self.y})'
elif format_spec == 'verbose':
return f'Point at X={self.x}, Y={self.y}'
else:
# 默认行为,或者回退到 __str__()
return f'Point: {self.x}, {self.y}'
# 创建 Point 类的实例
p = Point(10, 20)
# 使用 format() 函数
print(format(p, 'coords'))
print(format(p, 'verbose'))
print(format(p, '')) # 没有指定格式说明符
# 使用 f-string
print(f'Coordinates: {p:coords}')
print(f'Details: {p:verbose}')
print(f'Default: {p}')
运行结果如下。
(10, 20)
Point at X=10, Y=20
Point: 10, 20
Coordinates: (10, 20)
Details: Point at X=10, Y=20
Default: Point: 10, 20
分析:
在这个例子中,我们定义了一个 Point 类,并为其实现了 __format__() 方法。该方法根据传入的 format_spec 参数返回不同的字符串表示:
- 当 format_spec 为 'coords' 时,返回坐标形式 (x, y)。
- 当 format_spec 为 'verbose' 时,返回更详细的描述。
- 当 format_spec 为空字符串(即没有指定格式说明符)时,返回默认的 Point: x, y 形式。
示例 2:__format__() 模拟内置类型的格式化行为
class Currency:
def __init__(self, amount, symbol='¥'):
self.amount = amount
self.symbol = symbol
def __format__(self, format_spec):
if not format_spec:
return f'{self.symbol}{self.amount:.2f}' # 默认保留两位小数
# 尝试解析格式说明符,类似于浮点数
# 简单实现,不处理所有复杂情况
if '.' in format_spec:
precision = int(format_spec.split('.')[-1][0]) # 提取精度
return f'{self.symbol}{self.amount:.{precision}f}'
else:
return f'{self.symbol}{self.amount}{format_spec}'
# 创建 Currency 类的实例
price = Currency(32.56)
discount = Currency(9.8)
# 使用不同的格式说明符
print(f'Price: {price}') # 默认格式
print(f'Price: {price:.1f}') # 一位小数
print(f'Price: {price:.4f}') # 四位小数
print(f'Discount: {discount}')
print(f'Discount: {discount:.0f}') # 整数部分
运行结果如下。
Price: ¥32.56
Price: ¥32.6
Price: ¥32.5600
Discount: ¥9.80
Discount: ¥10
分析:
在 Currency 类中,我们手动实现了 __format__() 方法。该方法会尝试解析 format_spec 以支持小数点精度。
虽然这是一个简化的实现,但它展示了 __format__() 如何允许自定义对象模拟内置数据类型的复杂格式化规则。例如,当 {price:.1f} 调用时,format_spec 为 '.1f',方法解析出精度 “1” 并相应地格式化金额。
示例 3:没有实现 __format__() 方法
class MyObject:
def __init__(self, value):
self.value = value
def __str__(self):
return f'MyObject({self.value})'
def __repr__(self):
return f'<{self.__class__.__name__} object at {id(self)} value={self.value}>'
obj = MyObject(666)
print(format(obj, ''))
运行结果如下。
MyObject(666)
分析:
如果一个类没有定义 __format__() 方法,那么当我们尝试对其进行格式化时,Python 会回退到其默认的字符串表示(通常是 __str__() 或 __repr__())。
