可以像oct()和hex()一样重载bin()吗?
在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 个回答
bin函数的值是通过对象的__index__
函数来获取的。也就是说,对于一个对象,你可以定义它转换成二进制时的值,但你不能定义这个字符串的格式。
正如你已经发现的那样,你不能重写 bin()
函数,但听起来你并不需要这样做。你只是想要一个带有前导零的二进制值。可惜在 Python 2.5 及之前的版本中,你不能用 "%b" 来表示二进制,所以你不能使用 "%" 字符串格式化操作符来达到你想要的结果。
幸运的是,Python 2.6 提供了你需要的功能,使用新的 str.format() 方法。我相信这段看起来有点复杂的代码就是你在找的:
>>> '{0:010b}'.format(19)
'0000010011'
这个小语言的语法在文档中的 "格式规范小语言" 部分有介绍。为了节省你的时间,我来解释一下我使用的字符串:
- 第一个参数(也就是
19
)需要被格式化,使用 - 一个神奇的 "
0
" 来表示我想要一个带有前导零的、右对齐的数字, - 精确到 10 位数字,
- 以二进制格式显示。
你可以使用这种语法来实现各种创意的对齐和填充效果。
我觉得简单的回答就是‘不,bin()
不能像oct()
和hex()
那样被重载。’
至于为什么,答案要追溯到Python 3.0。在这个版本中,__index__
被用来重载hex()
、oct()
和bin()
,而__oct__
和__hex__
这些特殊功能则完全被移除了。
所以,Python 2.6中的bin()
看起来很像是Python 3.0的一个特性,只是被移植过来,但并没有考虑到它是按照新的Python 3方式在运行,而不是旧的Python 2方式。我还猜测,即使这被认为是个bug,也不太可能会去修复它。