我使用的是第三方模块,它提供从tuple
继承的类。但是,我想在这些类中添加一些功能,所以我有了子类。结果继承层次结构如下所示:
MyClass
->;LibClass
->;tuple
从tuple
子类的继承有什么原因应该是预期的失败吗?在
一开始一切似乎都很好。但是,使用切片(instance[:6]
)从MyClass
的实例访问一系列值会导致如下错误:
SystemError: <method-wrapper '__getitem__' of LibClass object at 0x1010101010> returned NULL without setting an error
对LibClass
的实例执行完全相同的操作可以完美地工作。在
为了进一步增加神秘感,对MyClass
实例的常规索引访问(instance[5]
)可以完美地工作。在
显然tuple
继承与正则类继承不同(即__new__
必须被重写,而不是{LibClass
是正确的
def __new__(cls, *members):
mat = [x * 1.0 for x in members] + [0.0, 0.0, 1.0]
return tuple.__new__(cls, mat)
我不认为在MyClass
中实现__new__
是必要的,因为LibClass
中的实现正确地通过了{MyClass
中实现__new__
(只是复制并粘贴了LibClass
实现)。在
我还应该注意到我在MyClass
中没有做任何古怪的事情。如果问题仍然存在,那就什么也不做
另一件值得注意的事情是,LibClass
没有自定义的__getitem__
实现,它只是从tuple
继承该行为。在
Python 3.6.1
LibClass
实际上Affine
来自planar
,我的叉子可以在这里找到:
https://github.com/Benjamin-Dobell/planar/blob/master/lib/planar/transform.py
pip install git+https://github.com/Benjamin-Dobell/planar#egg=planar
python
>>> import planar
>>> class Affine(planar.Affine):
... pass
...
>>> planar.Affine.identity()[:6]
(1.0, 0.0, 0.0, 0.0, 1.0, 0.0)
>>> Affine.identity()[:6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: <method-wrapper '__getitem__' of Affine object at 0x10e2b9ba8> returned NULL without setting an error
在评论中指出,在上面的复制中,identity()
返回一个常量。所以它不应该失败。我无法解释。不过,我应该补充一点,这是一个相当差的复制我。我的实际使用量更接近于:
>>> Affine.translation((0, 0))[:6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: <method-wrapper '__getitem__' of Affine object at 0x10f8d5ee8> returned NULL without setting an error
>>> planar.Affine.translation((0, 0))[:6]
(1.0, 0.0, 0.0, 0.0, 1.0, 0.0)
但同样失败了。在
请注意,这种不断的失败真让我抓狂。在
planar
特定的东西尝试不同的Python版本时,同样失败:
Python 3.3.6 (default, Apr 12 2017, 17:20:32)
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import planar
>>> class Affine(planar.Affine):
... pass
...
>>> planar.Affine.identity()[:6]
(1.0, 0.0, 0.0, 0.0, 1.0, 0.0)
>>> Affine.identity()[:6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: NULL result without error in PyObject_Call
Python 2.7.11 (default, May 2 2016, 14:38:51)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import planar
>>> class Affine(planar.Affine):
... pass
...
>>> planar.Affine.identity()[:6]
(1.0, 0.0, 0.0, 0.0, 1.0, 0.0)
>>> Affine.identity()[:6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: NULL result without error in PyObject_Call
但是,当把问题简化为最简单的形式时,我无法重现这个问题(Python 2.7.11):
>>> class LibClass(tuple):
... def __new__(cls, *members):
... return tuple.__new__(cls, *members)
...
>>> class MyClass(LibClass):
... pass
...
>>> LibClass((1, 2, 3, 4, 5))[:3]
(1, 2, 3)
>>> MyClass((1, 2, 3, 4, 5))[:3]
(1, 2, 3)
我还尝试将LibClass
的定义移动到一个单独的lib.py
,以确保错误与Python模块无关,但它的工作原理如上所述。在
所以这个问题是planar
和/或其Affine
类特有的问题。不过,如果能确切知道是什么导致了这个问题,那就太好了。在
事实证明确实涉及到一个有缺陷的扩展模块。
planar
根本没有使用您编辑过的planar.transform
模块;它使用的是planar.c
,这是planar
功能的一个C实现,带有自己的Affine
类。在问题至少有一部分似乎是由于^{} 中的错误造成的:
其中,它返回
NULL
,而不为超出范围的索引设置IndexError
。在planar
不再维护,因此不会处理错误报告。可能有更好的模块可以使用。在相关问题 更多 >
编程相关推荐