5

在 Python 中模仿 C# 中的虚函数和纯虚函数的最佳方法是什么?

目前我使用如下模式:

class AbstractClass(object):
    '''Abstract class'''
    def __init__(self):
        assert False, 'Class cannot be instantiated'

    def _virtual_init(self):
        print 'Base "constructor"'

    def pure_virtual_function(self):
        assert False, 'Pure virtual function should be derived'

    def virtual_function(self):
        print 'Base: virtual function'

class Derived1(AbstractClass):
    '''All functions derived'''
    def __init__(self):
        print 'Derived1: constructor'
        AbstractClass._virtual_init(self)

    def pure_virtual_function(self):
        print 'Derived1: pure virtual function'

    def virtual_function(self):
        print 'Derived1: virtual function'

class Derived2(AbstractClass):
    '''Pure virtual method missing.'''
    def __init__(self):
        print 'Derived2: constructor'
        AbstractClass._virtual_init(self)

    def virtual_function(self):
        print 'Derived3: virtual function'

class Derived3(AbstractClass):
    '''Virtual method missing (use base class)'''
    def __init__(self):
        print 'Derived3: constructor'
        AbstractClass._virtual_init(self)

    def pure_virtual_function(self):
        print 'Derived3: pure virtual function'


# ab = AbstractClass() # Gives error -> OK

print 'DERIVED 1'    
dv1 = Derived1()
dv1.pure_virtual_function()
dv1.virtual_function()

print 'DERIVED 2'    
dv2 = Derived2()
# dv2.pure_virtual_function() # Gives error: Pure virtual function should be derived -> OK
dv2.virtual_function()

print 'DERIVED 3'    
dv3 = Derived3()
# dv3.pure_virtual_function() # Gives error: Pure virtual function should be derived -> OK
dv3.virtual_function()

我得到输出:

DERIVED 1
Derived1: constructor
Base "constructor"
Derived1: pure virtual function
Derived1: virtual function
DERIVED 2
Derived2: constructor
Base "constructor"
Derived3: virtual function
DERIVED 3
Derived3: constructor
Base "constructor"
Derived3: pure virtual function
Base: virtual function

但是我的具体问题是:

  1. 有没有更优雅的方式在 Python (2.7) 中定义抽象基类?上述解决方案仅在运行时给出错误(例如使用 pylint) Python afaik 中没有“抽象”关键字。
  2. 有没有更优雅的方式在 Python(2.7)中定义纯虚方法?同样,上述解决方案仅在运行时给出错误。
  3. 有没有更优雅的方式在 Python (2.7) 中定义虚拟方法?不需要检查,但在 Python afaik 中没有像“virtual”这样的关键字。

提前致谢。

4

2 回答 2

5

当您询问虚拟方法时,我不确定您到底是什么意思,因为在 Python 中所有方法都是虚拟的。而且我也不确定你为什么使用_virtual_init而不是__init__......只是重命名一个方法会给你带来一些东西吗?

更新:啊,我有个主意。您可能这样做是为了禁止基类的实例化仍然保留初始化功能。这里的答案是:强迫事情不是pythonic。只需记录这个类是抽象的(并且可能称之为AbstractSmth)。

谈到运行时错误。Python 是一种动态语言,所以它就是这样工作的。一个常见的习惯用法是NotImplementedError用来__init__表明您的类是抽象的(对于抽象(纯虚拟)方法也是如此)。你也可以看看abc它做你想做的事:它禁止实例化抽象类。但我也强烈建议阅读PEP-3119以了解抽象基类什么以及它们不是什么。

AFAIK,提升NotImplementedError足以让 pylint 了解您的类/方法是抽象的。

于 2013-06-13T13:44:51.163 回答
0
class AbstractBaseClass(object):
    def __init__(self):
        if self.__class__.__name__ == 'AbstractBaseClass':
            raise NotImplementedError("Can't instantiate AbstractBaseClass")

class DerivedClass(AbstractBaseClass):
    def __init__(self):
        super().__init__()
        # ...

此示例显示派生类(具有不同__class__.__name__成员)可以被实例化,并继承 AbstractBaseClass 提供的属性。但是如果 AbstractBaseClass 被直接实例化,NotImplementedError就会抛出异常。

于 2016-12-27T21:22:29.400 回答