【问题标题】:How to overload same named methods of different interfaces with type annotations in Python 3如何在 Python 3 中使用类型注释重载不同接口的相同命名方法
【发布时间】:2020-07-12 16:31:01
【问题描述】:

所以我有这样的 Python 3 代码:

from abc import ABC, abstractmethod                                                                                                                                                                                                                                                         
from datetime import datetime                                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                            
class IfaceA(ABC):                                                                                                                                                                                                                                                                          
    @abstractmethod                                                                                                                                                                                                                                                                         
    def pass_data(self, data: str):                                                                                                                                                                                                                                                         
        pass                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                            
class IfaceB(ABC):                                                                                                                                                                                                                                                                          
    @abstractmethod                                                                                                                                                                                                                                                                         
    def pass_data(self, data: datetime):                                                                                                                                                                                                                                                    
        pass                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                            
class MyClass(IfaceA, IfaceB):                                                                                                                                                                                                                                                              
    def pass_data(self, data: str):                                                                                                                                                                                                                                                         
        print("str", data)                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                            
    def pass_data(self, data: datetime):                                                                                                                                                                                                                                                    
        print("datetime", data)                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                            
def main():                                                                                                                                                                                                                                                                                 
    c = MyClass()                                                                                                                                                                                                                                                                           
    c.pass_data("Any string.")                                                                                                                                                                                                                                                              
    c.pass_data(datetime.now())                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                            
if __name__ == "__main__":                                                                                                                                                                                                                                                                  
    main()

它给了我这样的输出:

datetime Any string.
datetime 2020-07-13 02:00:34.676715

未使用带有 str 参数的 IfaceA.pass_data 方法。

有没有办法让这项工作像在 C++ 中一样工作?

【问题讨论】:

    标签: python python-3.x interface polymorphism overloading


    【解决方案1】:

    你可以使用多种方法

     from abc import ABC, abstractmethod                                                                                                                                                                                                                                                         
    from datetime import datetime                                                                                                                                                                                                                                                               
    from multimethod import multimethod
                                                                                                                                                                                                                                                                                              
    class IfaceA(ABC):                                                                                                                                                                                                                                                                          
        @abstractmethod                                                                                                                                                                                                                                                                         
        def pass_data(self, data: str):                                                                                                                                                                                                                                                         
            pass                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                
    class IfaceB(ABC):                                                                                                                                                                                                                                                                          
        @abstractmethod                                                                                                                                                                                                                                                                         
        def pass_data(self, data: datetime):                                                                                                                                                                                                                                                    
            pass                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                
    class MyClass(IfaceA, IfaceB):
        @multimethod                                                                                                                                                                                                                                                           
        def pass_data(self, data: str):                                                                                                                                                                                                                                                         
            print("str", data)
        @multimethod                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
        def pass_data(self, data: datetime):                                                                                                                                                                                                                                                    
            print("datetime", data)                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                
    def main():                                                                                                                                                                                                                                                                                 
        c = MyClass()                                                                                                                                                                                                                                                                           
        c.pass_data("Any string.")                                                                                                                                                                                                                                                              
        c.pass_data(datetime.now())                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                
    if __name__ == "__main__":                                                                                                                                                                                                                                                                  
        main()
    

    【讨论】:

    • TypeError:元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类。我认为是因为 ABC 不是纯接口,我们这里有一个 Diamond-Problem。
    【解决方案2】:

    如果没有一些丑陋的非 Python 黑客,我认为这是不可行的。在没有 hack 或 3rd 方库(带有 hack)的情况下,您能做的最好的事情就是这样。

    from datetime import datetime
    from functools import singledispatchmethod
    
    
    class MyClass:
        @singledispatchmethod
        def pass_data(self, val):
            raise NotImplementedError
    
        @pass_data.register
        def prints_str(self, data: str):
            print("str", data)
    
    
        @pass_data.register
        def prints_datetime(self, data: datetime):
            print("datetime", data)
    
    
    def main():
        c = MyClass()
        c.pass_data("Any string.")
        c.pass_data(datetime.now())
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 2020-04-22
      • 2011-04-09
      • 1970-01-01
      • 2015-02-05
      • 2016-12-23
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      相关资源
      最近更新 更多