【问题标题】:Duck typing in practice - Python 3.7实践中的鸭子打字 - Python 3.7
【发布时间】:2019-12-23 19:57:46
【问题描述】:

我用 Python 编写了一个库,我想编写一个自我解释的代码,但我发现很难使用鸭式打字。

假设我有一个接受参数 A 的类。 该参数必须实现 fly、eat 和 dance 方法。 如果不阅读整个类的代码或辅助函数的代码,其他程序员甚至我自己如何轻松知道 A 参数必须实现什么行为?

这些天来,我在每个包含解释的 bahvior 的类上方定义了一个接口 - 用于自我解释的代码。

有什么想法吗?更好的灵魂?

【问题讨论】:

    标签: python python-3.x architecture python-3.7 duck-typing


    【解决方案1】:

    您的示例听起来像abstract class。您可以定义一个抽象类,并为该参数添加类型注释或显式检查其类型:

    from abc import ABC, abstractmethod
    
    class MyABC(ABC):
        @abstractmethod
        def fly(self):
            pass
    
        @abstractmethod
        def eat(self):
            pass
    
        @abstractmethod
        def dance(self):
            pass
    

    对于你的方法:

    def test(param: MyABC):
        if not isinstance(param, MyABC):
            raise Exception("param must inherit MyABC.")
    

    这是可行的,因为当将param 传递给test 方法时,它必须继承MyABC - 为了继承MyABC,该类必须定义三个方法flyeat、@987654333 @ - 否则,在尝试实例化它时会引发 TypeError

    编辑

    如果您希望子类直接继承但仍“算作”MyABC 子类,则可以使用__subclasshook__

    from abc import ABC, abstractmethod
    
    class MyABC(ABC):
        @abstractmethod
        def fly(self):
            pass
    
        @abstractmethod
        def eat(self):
            pass
    
        @abstractmethod
        def dance(self):
            pass
    
        @classmethod
        def __subclasshook__(cls, C):
            if any("fly" in B.__dict__ for B in C.__mro__):
                # add checks for dance and eat...
                return True
            return NotImplemented
    

    现在每个实现fly 方法(或继承实现它的类)的类都会将True 返回到以下条件: isinstance(CLASS, MyABC)

    来自流利的Python

    子类钩子在整个鹅类型命题中添加了一些鸭子类型的 DNA。您可以使用 ABC 进行正式的接口定义,您可以在任何地方进行 isinstance 检查,并且仍然有一个完全不相关的类,因为它实现了某个方法(或者因为它尽一切努力说服子类挂钩来保证它)。当然,这只适用于提供子类挂钩的 ABC。

    【讨论】:

    • 这正是我写“接口”时的意思。问题是它似乎不是 pythonic .. 但我找不到在 Python 中编写可读鸭子类型代码的其他方法
    • 我看不出这不是 Pythonic 的原因。
    • 好的。如果强制某个对象具有如下所示的 setter 和 getter:object.attribute 和 object.attribute = value。我的抽象类必须声明它,但是首选哪种方式?作为全球班级的成员?作为抽象属性?作为抽象数据类?
    • 你的意思是一个抽象的属性。这是一个单独的 SO 问题的主题。检查herehere
    • 您强制类型为 MyABC 实例。如果它具有所有提到的行为但不是该类的实例怎么办?这就是为什么我之前写过它反对 Duck Typing。我认为 Python 需要添加行为机制而不是抽象类,这将使 Python 成为真正的鸭式语言。
    猜你喜欢
    • 2011-03-23
    • 2011-11-25
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 2011-05-11
    相关资源
    最近更新 更多