如何子类化整数并使其可变

2024-09-30 12:25:41 发布

您现在位置:Python中文网/ 问答频道 /正文

是否可以将int子类化并使其可变?在

考虑以下类别:

class CustomBitVector(int):

    # bit 7
    @property
    def seventh_property(self):
        return bool(self & (1 << 7))

    @seventh_property.setter
    def seventh_property(self, val):
        self |= bool(val) << 7

    # bit 6
    @property
    def sixth_property(self):
        return bool(self & (1 << 6))

    @sixth_property.setter
    def sixth_property(self, val):
        self |= bool(val) << 6


    # ... a few more of these ...

    # bit 0
    @property
    def zeroth_property(self):
        return bool(self & (1 << 0))

    @zeroth_property.setter
    def zeroth_property(self, val):
        self |= bool(val) << 0

我试着做一个好的接口到一个位向量。我正在从一个套接字上读取一个专有协议,我创建了一些类来表示我正在发送/接收的消息。通常这些消息包括位向量,这样处理它们会很好。在

这对于读取位向量值非常有效,但是设置它们却不起作用,因为int是不可变的。在

如果我重写其中一个setters,比如:

^{pr2}$

然后我得到这样的行为:

In [2]: c = CustomBitVector()

In [3]: c.sixth_property
Out[3]: False

In [4]: c.sixth_property = True
before: 0
after: 64

In [5]: c
Out[5]: 0

In [6]: c.sixth_property
Out[6]: False

我能看出我的愚蠢。。。我将赋值给self,而不是修改它。在这种情况下,如何修改self?在

有什么疯狂的黑客行为能让这一切发生吗?也许用元类什么的?在


更新

我忘了提一个要求:

CustomBitVector的实例的行为必须类似于int。特别是,我需要能够将它们传递给struct.pack


Tags: inselfreturndefbitpropertyvalout
3条回答

我只需要打包我的概念验证代码,然后上传一个mutableint包到PyPi。在

https://pypi.org/project/mutableint/

下面是用法。在

from mutableint import MutableInt

# create a mutable integer with value 10 
a = MutableInt(10)

# change the value of a to 11
a.set(11)
^{bq}$

差不多吧。您可以添加所需的所有可变部分,但不能接触int部分,因此可以添加的可变程度对您没有帮助。在

相反,不要使用int子类。使用存储int的常规对象。如果希望能够像int一样将其传递给struct.pack,请实现__index__方法来定义如何将对象解释为int:

class IntLike(object): # not IntLike(int):
    def __init__(self, value=0):
        self.value = value
    def __index__(self):
        return self.value
    ...

您可以为|实现其他方法,如__or__,以及{}的{}的方法。不过,不要试图过分强调与int的完全互操作性;例如,不要试图使对象可用作dict键。毕竟它们是可变的。在

如果您的类是一个int子类,那么您将不得不牺牲您想要的c.sixth_property = True语法。您必须选择一个类似c = c.with_sixth_property(True)的替代方案,并以非变异的方式实现。在

这是我的解决方案。它也使整数也可迭代。在

import ctypes

class MutableInt(int):
    def __init__(self, val = 0):
        self._val = val

    def __int__(self):
        return self._val

    def __index__(self):
        return self._val

    def __str__(self):
        return str(self._val)

    def __repr__(self):
        return repr(self._val)

    def __iter__(self):
        self._iter_cnt = 0
        return self

    def __next__(self):
        if self._iter_cnt == 0:
            self._iter_cnt = 1
            return self._val
        else:
            raise StopIteration

    def set(self, val):
        self._val = val
        ob_digit = ctypes.c_long.from_address(id(self)+24)
        ob_digit.value = val

相关问题 更多 >

    热门问题