如何在Python中子类化array.array并使衍生构造函数不带参数?

4 投票
3 回答
2635 浏览
提问于 2025-04-16 11:02

我想把一个Python数组封装起来,固定它的类型代码,并且让用户看不见这个数组。我原本想通过继承来实现这个目标,但我发现自己无法构建我的类型,因为缺少一个必要的参数:

class MyBinaryBuffer(array.array):
    def __init__(self):
        array.array.__init__(self, 'B') #this is the fixed 'B' typecode parameter for 
                                  #array.array() constructor

myBuffer = MyBinaryBuffer()

我得到了:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: array() takes at least 1 argument (0 given)

我该如何以自然的方式实现这个呢?

经过一些研究,我发现应该使用构造函数来代替。

编辑: Sven Marnach建议我添加self,这让我想到了在__new__方法中添加缺失的cls参数,这样就成功了

class MyBinaryBuffer(array.array):
    def __new__(cls):
        return super(MyBinaryBuffer, cls).__new__(cls, 'B')

myBuffer = MyBinaryBuffer()

3 个回答

0

这里有一个在python2.x和python3.x中都经过测试的方法:

from array import array


class MyBinaryBuffer(array):
    def __new__(cls, *args, **kwargs):
        return super(MyBinaryBuffer, cls).__new__(cls, 'B', *args, **kwargs)


b1 = MyBinaryBuffer([1, 2, 3])
b2 = MyBinaryBuffer()
print(b1, b2)

或者,如果你想避免使用 super

class MyBinaryBuffer(array):
    def __new__(cls, *args, **kwargs):
        return array.__new__(cls, 'B', *args, **kwargs)

在这个特定的情况下,你将能够完全模拟 array.array 的行为,其他现有的答案并不能保证这一点。

0

如果你想添加自己的属性,可以使用newinit

举个例子:

class Point(array.array):
    '''
    an array.array with 3 coordinates [x,y,z]
    '''

    def __new__(cls, clist, parent=None, index=-1):
        while len(clist)<3: clist.append(0.0)
        return super(Point, cls).__new__(cls,'f', clist[0:3])


    def __init__(self, cList=[], parent=None, index=-1):
        self._parent = parent  # private
        self.index   = index   # public

    @property
    def parent(self):
        return self._parent

p = Point([1,2], parent='anyObject', index=5)
print(p, p.parent, p.index) 
6

你需要使用 __new__ 方法,因为 __init__ 方法是在对象已经创建好的情况下被调用的。不过在这里你不需要使用 super

class OctetString(array):
    def __new__(cls):
        return array.__new__(cls, 'c')

撰写回答