【问题标题】:Able to instantiate python class, in spite of it being Abstract (using abc)能够实例化 python 类,尽管它是抽象的(使用 abc)
【发布时间】:2014-08-05 18:31:19
【问题描述】:

这是参考this question对“使用python的abc模块创建抽象类”的答案。 (@alexvassel 并被接受为答案)。

我尝试了这些建议,但奇怪的是,尽管遵循了使用abc 方式的建议,但它对我不起作用。因此,我将其作为问题发布在这里:

这是我的 Python 代码:

from abc import ABCMeta, abstractmethod

class Abstract(object):
    __metaclass__ = ABCMeta

    @abstractmethod
    def foo(self):
        print("tst")

a = Abstract()
a.foo()

当我执行这个模块时,这是我控制台上的输出:

pydev debugger: starting (pid: 20388)
tst

与接受的答案相反

>>> TypeError: Can not instantiate abstract class Abstract with abstract methods foo

那么我做对了还是错了?为什么工作而不失败?感谢任何专家对此的见解。

【问题讨论】:

    标签: python python-3.x abstract-class python-2.x abstract-base-class


    【解决方案1】:

    在 Python 3 中,在创建抽象基类时使用 metaclass 参数:

    from abc import ABCMeta, abstractmethod
    
    class Abstract(metaclass=ABCMeta):
    
        @abstractmethod
        def foo(self):
            print("tst")
    
    a = Abstract()
    a.foo()
    

    【讨论】:

    • 我明白了。这是很好的信息。在我按照建议修改定义后它可以工作。谢谢。
    • 如果抽象类没有任何@abstractmethod,您似乎可以实例化和调用方法
    【解决方案2】:

    在 Python 2 中,您必须这样分配元类:

    import abc
    
    class ABC(object):
    
        __metaclass__ = abc.ABCMeta
    
        @abc.abstractmethod
        def foo(self):
            return True
    
    a = ABC()
    

    这会引发TypeError

    Traceback (most recent call last):
      File "<pyshell#59>", line 1, in <module>
        a = ABC()
    TypeError: Can't instantiate abstract class ABC with abstract methods foo
    

    但在 Python 3 中,将 __metaclass__ 分配为属性不起作用(如您所愿,但解释器不认为这是一个错误,只是一个普通属性,这就是上面代码的原因不会引发错误)。元类现在被定义为类的命名参数:

    import abc
    
    class ABC(metaclass=abc.ABCMeta):
    
        @abc.abstractmethod
        def foo(self):
            return True
    
    a = ABC()
    

    提出TypeError

    Traceback (most recent call last):
      File "main.py", line 11, in 
        a = ABC()
    TypeError: Can't instantiate abstract class ABC with abstract methods foo
    

    【讨论】:

    • 感谢您详细解释为什么它不会引发 Python 2 错误。我希望它这样做,而不是像我不打算那样默默地工作:(
    • @jark 有趣的是,您选择了 Victory 的代码,因为它对 Python 3 无效,并且实际上并没有展示您要查找的内容。
    • Aaron Hall,感谢您的反馈。我接受了胜利的回答,因为那是第一个进来的,我阅读并尝试过,它按我的预期工作。我不确定您为什么说它“对 Python 3 无效”?如果我将您在解决方案中发布的代码与 Victory 发布的代码进行比较,两者都使用完全相同的逻辑。唯一的区别是您使用“import abc”(然后使用 abc.abstract 方法等)与 Victory 使用“from abc import ABCMeta, abstractmethod”和使用 abstractmethod 等。没有任何个人反对你是为了胜利,
    • 感谢您的详细回答。但再次请让我知道我是如何误解了 Victory 的答案以及为什么它不起作用,我会考虑接受你的答案。
    • @jark 他在a = Abstract() 上的失败(应该如此)和a.foo() 无关紧要,很明显他没有测试他的代码,他只是复制了你的代码并对其进行了更改。不过,请接受您认为对您最有帮助的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-01-28
    • 2015-03-19
    • 1970-01-01
    • 2019-08-27
    • 2013-08-23
    • 2016-09-21
    相关资源
    最近更新 更多