如何继承int并使它可变 [英] How to subclass int and make it mutable
问题描述
是否可以将int
子类化并使其可变?
Is it possible to subclass int
and make it mutable?
请考虑以下课程:
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
我试图为位向量创建一个不错的接口.我正在从套接字读取专有协议,并且已经制作了一些类来表示我正在发送/接收的消息.这些消息通常包含位向量,因此最好像这样处理它们.
I trying to make a nice interface to a bit vector. I'm reading a proprietary protocol off of a socket and I've made classes to represent the messages I'm sending/receiving. Often these messages include bit vectors and it would be nice to deal with them like this.
这对于读取位向量值已经非常有用,但是由于int
是不可变的,因此无法设置它们.
This already works great for reading the bit vector values, but setting them doesn't work because int
is immutable.
如果我像以下那样重写二传手之一:
If I rewrite one of the setters like:
@sixth_property.setter
def sixth_property(self, val):
print 'before:', self
self |= bool(val) << 6
print 'after:', self
然后我得到这种行为:
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
?
I can see my folly ... I'm assigning to self
instead of modifying it. How can I modify self
in this case?
有没有疯狂的骇客来实现这一目标?也许使用元类之类的东西?
Any crazy hack to make this happen? Maybe using a metaclass or something?
我忘了提到一个要求:
CustomBitVector
的实例的行为必须类似于int
.特别是,我需要能够将它们传递给struct.pack
Instances of CustomBitVector
must behave like int
. In particular, I need to be able to pass them to struct.pack
推荐答案
是否可以继承int并使其可变?
Is it possible to subclass int and make it mutable?
排序.您可以添加所需的所有可变部分,但不能触摸整数部分,因此可以添加的可变性对您没有帮助.
Sort of. You can add all the mutable parts you want, but you can't touch the int parts, so the degree of mutability you can add won't help you.
相反,不要使用int子类.使用存储int的常规对象.如果您希望能够像int一样将其传递给struct.pack
,请实现__index__
方法以定义如何将对象解释为int:
Instead, don't use an int subclass. Use a regular object that stores an int. If you want to be able to pass it to struct.pack
like an int, implement an __index__
method to define how to interpret your object as an int:
class IntLike(object): # not IntLike(int):
def __init__(self, value=0):
self.value = value
def __index__(self):
return self.value
...
您可以实现其他方法,例如对于|
的__or__
和对于就地可变|=
的__ior__
.但是,不要试图为与int的完全互操作性而过分努力;例如,请勿尝试使您的对象可用作dict键.毕竟它们是可变的.
You can implement additional methods like __or__
for |
and __ior__
for in-place, mutative |=
. Don't try to push too hard for complete interoperability with ints, though; for example, don't try to make your objects usable as dict keys. They're mutable, after all.
如果您的类是int
子类对您而言确实很重要,那么您将不得不牺牲您想要的c.sixth_property = True
语法.您必须选择c = c.with_sixth_property(True)
之类的替代方法,并以非可变方式实现.
If it's really important to you that your class is an int
subclass, you're going to have to sacrifice the c.sixth_property = True
syntax you want. You'll have to pick an alternative like c = c.with_sixth_property(True)
, and implement things non-mutatively.
这篇关于如何继承int并使它可变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!