Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有另一个基类的python abstractmethod破坏了抽象功能_Python_Multiple Inheritance_Metaclass_Abstract Methods - Fatal编程技术网

带有另一个基类的python abstractmethod破坏了抽象功能

带有另一个基类的python abstractmethod破坏了抽象功能,python,multiple-inheritance,metaclass,abstract-methods,Python,Multiple Inheritance,Metaclass,Abstract Methods,考虑下面的代码示例 导入abc abc类测试(abc.abc): @抽象方法 def foo(self): raise RUNTIMERROR(“调用了抽象方法,这应该是不可能的”) ABCtest_B类(ABCtest): 通过 测试=ABCtest_B() 这会正确地引发错误: Traceback (most recent call last): File "/.../test.py", line 10, in <module> test = ABCtest_B()

考虑下面的代码示例

导入abc
abc类测试(abc.abc):
@抽象方法
def foo(self):
raise RUNTIMERROR(“调用了抽象方法,这应该是不可能的”)
ABCtest_B类(ABCtest):
通过
测试=ABCtest_B()
这会正确地引发错误:

Traceback (most recent call last):
  File "/.../test.py", line 10, in <module>
    test = ABCtest_B()
TypeError: Can't instantiate abstract class ABCtest_B with abstract methods foo

从C中定义的任何类(包括
itertools.chain
numpy.ndarray
)继承时,似乎都会发生这种情况,但仍然正确地引发python中定义的类的错误。为什么实现一个内置类型会破坏抽象类的功能?

令人惊讶的是,阻止实例化抽象类的测试发生在中,而不是由
abc
模块本身定义的任何内容:

static PyObject *
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    ...
    if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) {
        ...
        PyErr_Format(PyExc_TypeError,
                     "Can't instantiate abstract class %s "
                     "with abstract methods %U",
                     type->tp_name,
                     joined);
(几乎是?)所有不是
对象的内置类型
都提供一个不同的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
来覆盖
对象。uuuuuuuuuuuuuuuuuuuuuuuuuuuuu。当您从非
对象
内置类型多次继承时,您将绕过抽象方法检查,继承其
\uuuuuuuuu新方法

abc
文档中,我没有看到任何关于
\uuuu new\uuuu
或内置类型的多重继承的内容。文档可以在这里使用增强功能

看起来有点奇怪,他们会在ABC实现中使用一个元类,这使得在抽象类中使用其他元类变得一团糟,然后在与
ABC
无关的核心语言代码中加入关键的检查,并为抽象类和非抽象类运行

自2009年以来,问题追踪者一直在关注这个问题。

我问了一个类似的问题,根据s链接的错误报告,我提出了这个解决方法(基于以下人员的建议):


这会引发
TypeError:无法实例化使用抽象方法bar、foo
派生的抽象类,这是原始行为。

@DonkeyKong(或任何其他没有得到它的人)通常情况下,应该在子类中强制重写方法
foo
(并且不从
str
继承)实例化它会引发一个错误,但是当同时从
str
初始化时,不会发生错误,并且抽象方法
test.foo
是一个有效的可调用方法。@Tadhgcdonald Jensen刚刚流行起来,谢谢:)@Torxed
str
不是一个变量名。我刚刚意识到,谢谢你让我读了两遍@DonkeyKong:)哦,见鬼,如果有人知道这个消息来源,我会很高兴的。但这是规范的一部分吗?是否存在需要这种行为的情况?或者它是一个bug,或者只是一个没有被考虑的案例?
static PyObject *
object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    ...
    if (type->tp_flags & Py_TPFLAGS_IS_ABSTRACT) {
        ...
        PyErr_Format(PyExc_TypeError,
                     "Can't instantiate abstract class %s "
                     "with abstract methods %U",
                     type->tp_name,
                     joined);
from abc import ABC, abstractmethod

class Base(ABC):
    @abstractmethod
    def foo(self):
        pass

    @abstractmethod
    def bar(self):
        pass

    def __new__(cls, *args, **kwargs):
        abstractmethods = getattr(cls, '__abstractmethods__', None)
        if abstractmethods:
            msg = "Can't instantiate abstract class {name} with abstract method{suffix} {methods}"
            suffix = 's' if len(abstractmethods) > 1 else ''
            raise TypeError(msg.format(name=cls.__name__, suffix=suffix, methods=', '.join(abstractmethods)))
        return super().__new__(cls, *args, **kwargs)

class Derived(Base, tuple):
    pass

Derived()