Python __format__() 方法

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__())。

上一篇: __bytes__()

下一篇: __hash__()

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号