在python中将属性添加到int值

shx*_*hx2 7 python int inheritance properties operators

我有一个值,通常在我的代码中以不同的单位使用.例如,以BYTES的数量表示缓冲区大小,但在许多地方将大小称为KB或MB(这只是一个示例,而不是我的实际用例).

为了优雅和易用,我想避免显式转换(例如size/1024,或b_to_mb(size)),因为它们在许多不同的地方都需要.

我认为我可以通过属性实现这一点,这使得转换变得容易(x.kbx.mb),并且还使调用者不知道存储的实际值的单位.

我的代码看起来像这样:

class BufferSize(int):
    @property
    def b(self):
        return int(self)
    @property
    def kb(self):
        return self.b / 1024
    @property
    def mb(self):
        return self.kb / 1024
Run Code Online (Sandbox Code Playgroud)

这有效,直到我使用算术运算符:

s = BufferSize(500000)
s.kb
=> 488.28125   # ok
s.mb
=> 0.476837158203125  # ok
type(s + BufferSize(0))
=> int  # type lost...
Run Code Online (Sandbox Code Playgroud)

有没有办法确保算术运算保留类型?也就是说,除了覆盖它们中的每一个之外?

或者也许是解决原始问题的另一种更好的方法?

JL *_*ret 2

好吧,与其说是重新实现,不如说是包装/转换int的魔术方法的结果,至少是那些返回ints.. 不幸的是,所有这些方法的结果。想知道是否不能使用装饰器或元类来加快速度。

class BufferSize(int):
    @property
    def b(self):
        return int(self)
    @property
    def kb(self):
        return self.b / 1024
    @property
    def mb(self):
        return self.kb / 1024

    def __add__(self, *args, **kwds):
        return BufferSize(super(BufferSize, self).__add__(*args, **kwds))

v = BufferSize(1) + BufferSize(2)

print v, type(v)
Run Code Online (Sandbox Code Playgroud)

输出:

3 <class '__main__.BufferSize'>
Run Code Online (Sandbox Code Playgroud)

我还考虑过直接将该属性添加到 int 本身,但快速测试排除了这种可能性。

>>> int.b = "b"
Run Code Online (Sandbox Code Playgroud)

输出:

 can't set attributes of built-in/extension type 'int'
Run Code Online (Sandbox Code Playgroud)