在Python中,如何在子类上强制抽象方法是静态的?

在Python中,如何在子类上强制抽象方法是静态的?,python,abstract-class,static-methods,abc,Python,Abstract Class,Static Methods,Abc,这是我想要的设置: A应该是具有静态和抽象方法f()的抽象基类。B应继承A.要求: 1.您不应该能够实例化 2.您应该不能实例化B,除非它实现了静态f() 从这个问题中得到启发,我尝试了几种方法。根据这些定义: class abstractstatic(staticmethod): __slots__ = () def __init__(self, function): super(abstractstatic, self).__init__(function)

这是我想要的设置: A应该是具有静态和抽象方法f()的抽象基类。B应继承A.要求: 1.您不应该能够实例化 2.您应该不能实例化B,除非它实现了静态f()

从这个问题中得到启发,我尝试了几种方法。根据这些定义:

class abstractstatic(staticmethod):
    __slots__ = ()
    def __init__(self, function):
        super(abstractstatic, self).__init__(function)
        function.__isabstractmethod__ = True
    __isabstractmethod__ = True

class A:
    __metaclass__ = abc.ABCMeta
    @abstractstatic
    def f():
        pass

class B(A):
    def f(self):
        print 'f'

class A2:
    __metaclass__ = abc.ABCMeta
    @staticmethod
    @abc.abstractmethod
    def f():
        pass

class B2(A2):
    def f(self):
        print 'f'
这里A2和B2是使用常见的Python约定定义的,A&B是使用答案中建议的方式定义的。以下是我尝试过的一些操作和不期望的结果

A/B类:

>>> B().f()
f
#This should have thrown, since B doesn't implement a static f()
对于A2/B2类:

>>> A2()
<__main__.A2 object at 0x105beea90>
#This should have thrown since A2 should be an uninstantiable abstract class

>>> B2().f()
f
#This should have thrown, since B2 doesn't implement a static f()
>>A2()
#由于A2应该是一个不可实例化的抽象类,因此应该引发此错误
>>>B2().f()
F
#这应该抛出,因为B2没有实现静态f()

既然这两种方法都没有给我想要的输出,我该如何实现我想要的呢?

你不能用
ABCMeta
做你想做的事。ABC强制执行不执行任何类型检查,只强制执行具有正确名称的属性的存在

例如:

>>> from abc import ABCMeta, abstractmethod, abstractproperty
>>> class Abstract(object):
...     __metaclass__ = ABCMeta
...     @abstractmethod
...     def foo(self): pass
...     @abstractproperty
...     def bar(self): pass
... 
>>> class Concrete(Abstract):
...     foo = 'bar'
...     bar = 'baz'
... 
>>> Concrete()
<__main__.Concrete object at 0x104b4df90>
使用此元类,您可以获得预期的输出:

>>> class Abstract(object):
...     __metaclass__ = ABCMetaTypeCheck
...     @abstractmethod
...     def foo(self): pass
...     @abstractproperty
...     def bar(self): pass
...     @abstractstatic
...     def baz(): pass
... 
>>> class ConcreteWrong(Abstract):
...     foo = 'bar'
...     bar = 'baz'
...     baz = 'spam'
... 
>>> ConcreteWrong()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class ConcreteWrong with abstract methods bar, baz, foo
>>> 
>>> class ConcreteCorrect(Abstract):
...     def foo(self): return 'bar'
...     @property
...     def bar(self): return 'baz'
...     @staticmethod
...     def baz(): return  'spam'
... 
>>> ConcreteCorrect()
<__main__.ConcreteCorrect object at 0x104ce1d10>
类抽象(对象): ... __元类=ABCMetaTypeCheck ... @抽象方法 ... def foo(自我):通过 ... @抽象属性 ... def bar(自我):通过 ... @抽象静态 ... def baz():通过 ... >>>类(摘要): ... foo='bar' ... bar='baz' ... baz=‘垃圾邮件’ ... >>>具体错误() 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:不能用抽象方法bar、baz、foo实例化抽象类ConcreteError >>> >>>类(摘要): ... def foo(self):返回“bar” ... @财产 ... def bar(自身):返回“baz” ... @静力学方法 ... def baz():返回“垃圾邮件” ... >>>具体正确()
>>> class Abstract(object):
...     __metaclass__ = ABCMetaTypeCheck
...     @abstractmethod
...     def foo(self): pass
...     @abstractproperty
...     def bar(self): pass
...     @abstractstatic
...     def baz(): pass
... 
>>> class ConcreteWrong(Abstract):
...     foo = 'bar'
...     bar = 'baz'
...     baz = 'spam'
... 
>>> ConcreteWrong()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class ConcreteWrong with abstract methods bar, baz, foo
>>> 
>>> class ConcreteCorrect(Abstract):
...     def foo(self): return 'bar'
...     @property
...     def bar(self): return 'baz'
...     @staticmethod
...     def baz(): return  'spam'
... 
>>> ConcreteCorrect()
<__main__.ConcreteCorrect object at 0x104ce1d10>