如何在 Python 3 中使用类型注释重载不同接口的相同命名方法

How to overload same named methods of different interfaces with type annotations in Python 3

所以我有 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++ 中一样工作?

你可以使用多方法

 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()

我认为如果没有一些丑陋的非 pythonic hack 是不可能的。没有黑客或第 3 方库(有黑客)你能做的最好的就是这个。

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()