gpt4 book ai didi

python - 从元组子类继承

转载 作者:太空宇宙 更新时间:2023-11-04 05:07:42 25 4
gpt4 key购买 nike

我正在使用第三方模块,该模块提供继承自 tuple 的类.但是,我想为这些类添加一些功能,所以我进行了子类化。生成的继承层次结构如下所示:

MyClass -> LibClass -> tuple

是否有任何理由继承自 tuple子类应该预期失败?

血淋淋的细节

一开始一切似乎都很美好。但是,利用切片 ( instance[:6] ) 从 MyClass 的实例访问一系列值导致如下错误:

SystemError: <method-wrapper '__getitem__' of LibClass object at 0x1010101010> returned NULL without setting an error

LibClass 的实例做完全相同的事情完美运行。

为了进一步增加神秘感,对 instance[5] 的实例进行常规索引访问 ( MyClass )完美运行。

显然 tuple继承并不完全像常规类继承(即 __new__ 必须被覆盖而不是 __init__ )。然而,据我所知LibClass这样做是否正确,例如

def __new__(cls, *members):
mat = [x * 1.0 for x in members] + [0.0, 0.0, 1.0]
return tuple.__new__(cls, mat)

我不相信实现 __new__MyClass考虑到 LibClass 中的实现是必要的正确通过 cls (诚​​然,我不得不 fork 图书馆来实现这一目标)。尽管如此,为了后代,我也确实尝试过实现 __new__直接在MyClass (只是复制并粘贴了 LibClass 实现)。

我还应该注意,我没有在 MyClass 中做任何古怪的事情。 .事实上,如果我什么都不做,问题仍然存在,例如

class MyClass(lib.LibClass):
pass

另一件值得注意的事情,LibClass没有自定义__getitem__实现 - 它只是从 tuple 继承该行为.

Python 3.6.1

额外的血腥(真实)细节

LibClass实际上是Affine来自 planar ,我的 fork 可以在这里找到:

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版本,同样失败:

3.3.6

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

2.7.11

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类(class)。不过,如果能确切知道是什么导致了问题,那就太好了。

最佳答案

事实证明确实涉及到一个有问题的扩展模块。 planar 根本没有使用您编辑的 planar.transform 模块;它使用 planar.cplanar 的功能的 C 实现,带有自己的 Affine 类。

至少部分问题似乎是由于 Affine_getitem 中的错误造成的:

static PyObject *
Affine_getitem(PlanarAffineObject *self, Py_ssize_t i)
{
double m;

assert(PlanarAffine_Check(self));
if (i < 6) {
m = self->m[i];
} else if (i < 8) {
m = 0.0;
} else if (i == 8) {
m = 1.0;
} else {
return NULL;
}
return PyFloat_FromDouble(m);
}

返回 NULL 而没有为超出范围的索引设置 IndexError

planar 不再维护,因此不会处理错误报告。可能有更好的模块可以使用。

关于python - 从元组子类继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43942880/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com