可以像oct()和hex()一样重载bin()吗?

16 投票
4 回答
2748 浏览
提问于 2025-04-15 12:17

在Python 2.6(以及更早的版本)中,hex()oct()这两个内置函数可以通过定义__hex____oct__这两个特殊函数来进行重载,也就是可以自定义它们的行为。不过,Python 2.6的新函数bin()却没有对应的__bin__特殊函数来进行重载。

我想知道有没有什么方法可以灵活地重载bin(),如果没有的话,我也想知道为什么会有这样的不一致。

我知道__index__这个特殊函数可以使用,但它的灵活性不高,因为它只能返回一个整数。我的具体需求来自于bitstring模块,在这个模块中,前导零位是被视为重要的:

>>> a = BitString(length=12)       # Twelve zero bits
>>> hex(a)
'0x000'
>>> oct(a)
'0o0000'
>>> bin(a)
'0b0' <------ I want it to output '0b000000000000'

我怀疑可能没有办法实现这个功能,但我觉得问问也无妨!

4 个回答

1

bin函数的值是通过对象的__index__函数来获取的。也就是说,对于一个对象,你可以定义它转换成二进制时的值,但你不能定义这个字符串的格式。

12

正如你已经发现的那样,你不能重写 bin() 函数,但听起来你并不需要这样做。你只是想要一个带有前导零的二进制值。可惜在 Python 2.5 及之前的版本中,你不能用 "%b" 来表示二进制,所以你不能使用 "%" 字符串格式化操作符来达到你想要的结果。

幸运的是,Python 2.6 提供了你需要的功能,使用新的 str.format() 方法。我相信这段看起来有点复杂的代码就是你在找的:

>>> '{0:010b}'.format(19)
'0000010011'

这个小语言的语法在文档中的 "格式规范小语言" 部分有介绍。为了节省你的时间,我来解释一下我使用的字符串:

  1. 第一个参数(也就是 19)需要被格式化,使用
  2. 一个神奇的 "0" 来表示我想要一个带有前导零的、右对齐的数字,
  3. 精确到 10 位数字,
  4. 以二进制格式显示。

你可以使用这种语法来实现各种创意的对齐和填充效果。

7

我觉得简单的回答就是‘不,bin()不能像oct()hex()那样被重载。’

至于为什么,答案要追溯到Python 3.0。在这个版本中,__index__被用来重载hex()oct()bin(),而__oct____hex__这些特殊功能则完全被移除了。

所以,Python 2.6中的bin()看起来很像是Python 3.0的一个特性,只是被移植过来,但并没有考虑到它是按照新的Python 3方式在运行,而不是旧的Python 2方式。我还猜测,即使这被认为是个bug,也不太可能会去修复它。

撰写回答