在 Python 中强制使用函数参数类型?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14858192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:40:08  来源:igfitidea点击:

Force a function parameter type in Python?

pythontypesinterface

提问by MintyAnt

I have a function in a Python class that adds Interfaces to a list.

我在 Python 类中有一个函数,可以将接口添加到列表中。

def RegisterAsListener(self, inListener):
    self.__TransitListeners.append(inListener)

This is nice, because a class just needs to inherit from said my Interface, grab this object, and register itself for all updates.

这很好,因为一个类只需要从我的接口继承,获取这个对象,并为所有更新注册自己。

class ITransit():
    def TransitUpdate(self, data):
        raise NotImplementedError("You must define this function.")

(assuming I made an interface correctly)

(假设我正确制作了一个界面)

Since i'm not the only one on this project, I don't want somebody calling the RegisterAsListener function with an incorrect data type. I could put in code to check the type within the register function, but it would be easier all around if the compiler just yelled at the programmer when they try to shove in an incorrect data type.

由于我不是这个项目中唯一的一个,我不希望有人使用不正确的数据类型调用 RegisterAsListener 函数。我可以输入代码来检查 register 函数中的类型,但是如果编译器在程序员试图输入不正确的数据类型时只是对他们大喊大叫,那么一切都会更容易。

def RegisterAsListener(self, IListener inListener):
    self.__TransitListeners.append(inListener)

Is there any way to do this?

有没有办法做到这一点?

采纳答案by Wolph

Although I would strongly recommend not doing this and only enforcing the implementation of certain methods using Abstract Base Classes (http://docs.python.org/2/library/abc.html), it is possible.

尽管我强烈建议不要这样做,而只使用抽象基类 ( http://docs.python.org/2/library/abc.html)强制实施某些方法,但这是可能的。

Here's an example on how to do something like that: http://www.artima.com/weblogs/viewpost.jsp?thread=101605

这是一个关于如何做这样的事情的例子:http: //www.artima.com/weblogs/viewpost.jsp?thread=101605

# mm.py
registry = {}                                                                   

class MultiMethod(object):                                                      
    def __init__(self, name):                                                   
        self.name = name                                                        
        self.typemap = {}                                                       
    def __call__(self, *args):                                                  
        types = tuple(arg.__class__ for arg in args) # a generator expression!  
        function = self.typemap.get(types)                                      
        if function is None:                                                    
            raise TypeError("no match")                                         
        return function(*args)                                                  
    def register(self, types, function):                                        
        if types in self.typemap:                                               
            raise TypeError("duplicate registration")                           
        self.typemap[types] = function                                          

def multimethod(*types):                                                        
    def register(function):                                                     
        function = getattr(function, "__lastreg__", function)                   
        name = function.__name__                                                
        mm = registry.get(name)                                                 
        if mm is None:                                                          
            mm = registry[name] = MultiMethod(name)                             
        mm.register(types, function)                                            
        mm.__lastreg__ = function                                               
        return mm                                                               
    return register                                                             

    if hasattr(function, "__lastreg__"):                                        
        function = function.__lastreg__

And the code using it:

以及使用它的代码:

import mm                                                                       

@mm.multimethod(int)                                                            
def spam(a):                                                                    
    print 'Calling the int method'                                              
    print '%s: %r' % (type(a), a)                                               

@mm.multimethod(float)                                                          
def spam(a):                                                                    
    print 'Calling the float method'                                            
    print '%s: %r' % (type(a), a)                                               

spam(5)                                                                         
spam(5.0)

Example output:

示例输出:

Calling the int method
<type 'int'>: 5
Calling the float method
<type 'float'>: 5.0

回答by JosefAssad

Since i'm not the only one on this project, I don't want somebody calling the RegisterAsListener function with an incorrect data type

由于我不是这个项目中唯一的一个,我不希望有人使用不正确的数据类型调用 RegisterAsListener 函数

Document the function thoroughly, then let incorrect parameters throw exceptions. The user of RegisterAListenershould be able to use the documentation to know what kind of data the function expects, and - if given incorrect parameters - the resulting exception should make it clear what the user of RegisterAListenerdid wrong.

彻底记录函数,然后让不正确的参数抛出异常。的用户RegisterAListener应该能够使用文档来了解函数期望的数据类型,并且 - 如果给定的参数不正确 - 产生的异常应该清楚地说明用户RegisterAListener做错了什么。