关于python:如何根据参数类型执行不同的操作

How to perform different actions depending on parameter type

在使用Java静态绑定的语言中,可以定义具有相同名称但不同参数的多个函数。学习python之前,我认为缺乏这一点主要是"安全问题"(比如bool_parameter="False"可能会因为引用而被解释为True)。我想我只需要更加小心。

现在我发现了一种情况,缺乏静态绑定是非常不方便的。请考虑这个图佩尔:

1
var = ((1,"foo"), (2,"bar"), (3,"potato"))

要从带有静态绑定的var中删除一个项,可以这样做(伪代码:

1
2
3
4
5
6
7
def del_item(int i):
    # search item with (x == i, *)
    # remove this item

def del_item(String s):
    # search item with (*, x == s)
    # remove this item

我觉得这很方便,因为不需要任何条件来选择要执行的正确操作。此外,此代码使重载更容易,因为您可以决定只重载其中一个函数或两者。

尝试在Python中处理这样的情况,我只发现一些不方便的解决方案,比如检查类型的if子句。

有更好的方法吗?


python没有方法重载,所以您必须检查参数的类型抱歉。

1
2
3
4
5
6
7
8
9
def del_item(item):
    if type(item) is int:
        # search item with (x == item, *)
        # remove this item
    elif type(item) is str:
        # search item with (*, x == s)
        # remove this item
    else:
        # Maybe raise an exception?


您的问题可以通过使用通用方法/函数来解决。这些不是内置于Python中的,但可以由第三方库或您自己编写一个库来连接。

几年前,我一直在和Peak规则一起愉快地工作,但尽管它仍然可以工作,但它似乎有点失宠了。

新的PEP443(单参数调度)伴随着外部实现single dispatch。https://pypi.python.org/pypi/singledispatch/3.4.0.3

有了这个,你的问题就可以这样解决了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 from functools import partial
 from singledispatch import singledispatch


 var = ((1,"foo"), (2,"bar"), (3,"potato"))


 @singledispatch
 def del_predicate(value):
     pass


 @del_predicate.register(int)
 def _(v, candidate):
     return v == candidate[0]

 @del_predicate.register(str)
 def _(v, candidate):
     return v == candidate[1]


 def neg(f):
     def _f(*args):
         return not f(*args)
     return _f

 print filter(neg(partial(del_predicate,"foo")), var)
 print filter(neg(partial(del_predicate, 2)), var)


看看这个问题:Python中isInstance()和type()的区别

如果您最终采用了建议的if-type方法,那么您可能需要考虑duck类型或isinstance替代方法。


您给出的特定情况似乎是无论如何都不需要重载的情况。

1
2
def del_item(id):
    return tuple(item for item in var if not id in item)

另一种选择是使用可选的关键字参数

1
2
3
4
def del_item(string_id=None, number_id=None):
    if string_id is not None:
        return tuple(item for item in var if not item[1] == string_id)
    return tuple(item for item in var if not item[0] == number_id)

前面有很多关于Python重载的问题,这是一个可能有助于理解为什么不将其视为问题的答案。