如何继承int并使它可变 [英] How to subclass int and make it mutable

查看:127
本文介绍了如何继承int并使它可变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆