如何在python中验证ducktyped接口?

2024-04-20 03:45:57 发布

您现在位置:Python中文网/ 问答频道 /正文

class ITestType(object):
  """ Sample interface type """

  __metaclass__ = ABCMeta

  @abstractmethod
  def requiredCall(self):
    return

class TestType1(object):
  """ Valid type? """
  def requiredCall(self):
    pass

class TestType2(ITestType):
  """ Valid type """
  def requiredCall(self):
    pass

class TestType3(ITestType):
  """ Invalid type """
  pass

在上面的例子中,issubclass(TypeType*, ITestType)对于2将返回true,对于1和3返回false。在

有没有其他方法可以使用issubclass,或者有一种接口测试的替代方法,允许12通过,但拒绝3?在

能够使用duck类型而不是显式地将类绑定到抽象类型,对我来说是非常有帮助的,而且允许在duck类型的对象通过特定接口时进行对象检查。在

是的,我知道python的人不喜欢接口,标准的方法是“当它失败时找到它,并将所有东西包装在异常中”,但也与我的问题完全无关。不,我不能简单地不在这个项目中使用接口。在

编辑:

太好了!对于发现此问题的其他人,下面是如何使用subclasshook的示例:

^{pr2}$

Tags: sample对象方法self类型objectdeftype
3条回答

这里有一个在实践中也非常有效的替代方法,不用在每次创建类实例时都检查整个字典。在

(py2和py3兼容)

用法:

class Bar():
  required_property_1 = ''

  def required_method(self):
    pass

# Module compile time check that Foo implements Bar
@implements(Bar)
class Foo(UnknownBaseClassUnrelatedToBar):
  required_property_1

   def required_method(self):
     pass

# Run time check that Foo uses @implements or defines its own __implements() member
def accepts_bar(self, anything):
  if not has_api(anything, Bar):
    raise Exception('Target does not implement Bar')
  ...

当@implements(Stream、Folder、Bar)都需要一些相同的方法时,您也可以做一些显而易见的事情,这使得这实际上比继承更有用。在

代码:

^{pr2}$

虽然晚了几年,但我是这样做的:

import abc

class MetaClass(object):
    __metaclass__ = abc.ABCMeta

    [...]

    @classmethod
    def __subclasshook__(cls, C):
        if C.__abstractmethods__:
            print C.__abstractmethods__
            return False
        else:
            return True

如果CMetaClass的尝试类,那么只有在{}实现所有抽象方法时,C.__abstractmethods__才会为空。在

有关详细信息,请参见此处:https://www.python.org/dev/peps/pep-3119/#the-abc-module-an-abc-support-framework(它在“实现”下,但是搜索__abstractmethods__应该可以找到正确的段落)

这对我有什么好处:

我可以创建MetaClass。然后我可以子类BaseClassMetaClass来创建需要一些额外功能的SubClass。但是我需要通过更改BaseClass属性将BaseClass的实例强制转换为SubClass,因为我没有{}属性,但是我得到了想要转换的实例。在

但是,如果我不正确地实现SubClass,我仍然可以强制转换,除非我使用上面的__subclasshook__并在执行强制转换过程时添加一个子类检查(我无论如何都应该这样做,因为我只想尝试向下转换父类)。如果有人要求,我可以提供一个MWE。在

埃塔:这是MWE。我认为我之前的建议是不正确的,所以下面的建议似乎符合我的意图。在

目标是能够将BaseClass对象转换为SubClass并返回。从SubClass到{}很容易。但从BaseClass到{}就不多了。标准的做法是更新__class__属性,但当{}不是真正的子类或从抽象的元类派生但没有正确实现时,这会留下一个空白。在

{{cd25>在下面的方法中实现了__abstractmethods__,看看它是否为空。如果是,那么它也是一个正确实现的元类。失败导致类型错误。否则对象将被转换。在

^{pr2}$

{检查^ a1}。您可以定义一个抽象基类,该抽象基类提供一个__subclasshook__方法,该方法根据您喜欢的任何条件(例如“它具有方法X、Y和Z”或其他任何条件)来定义特定类是否是抽象基类的“子类”。然后可以使用issubclass()isinstance()来检测类和实例上的接口。在

相关问题 更多 >