模仿方法重载是Pythonic吗?

时间:2010-09-04 14:51:52

标签: python

模仿静态类型语言中的方法重载是pythonic吗?我的意思是编写一个函数来检查其参数的类型,并根据这些类型的不同行为。

以下是一个例子:

class EmployeeCollection(object):
    @staticmethod
    def find(value):
        if isinstance(value, str):
            #find employee by name and return
        elif isinstance(value, int):
            #find employee by employee number and return
        else:
            raise TypeError()

5 个答案:

答案 0 :(得分:13)

不是真的,因为你失去了使用不那么接近但足够接近的类型的能力。相反,创建两个单独的方法(find_by_name()find_by_number())。

答案 1 :(得分:13)

不是非常Pythonic,除了,或许在2.6或更好的情况下,如果 all ,那么检查依赖于新的抽象基类,这些类基本上是为了方便使用。如果您发现自己正在为具体的类进行类型检查,那么您知道会使您的代码变得脆弱并限制其使用。

因此,例如,检查您是否有numbers.Integral的实例并不是太糟糕 - 新的ABC在很大程度上完全存在以简化此类检查。检查您是否有int实例是一场灾难,排除longgmpy.mpz以及其他类似整数的数字,绝对没有好处:绝不检查具体课程!

字符串是一个困难的案例,但basestring抽象类(不是新的ABCs之一)是可能的。也许有点过于严格了,但是如果你正在使用它周围的其他ABC,那么可能有点,有点工作,如果你真的需要。绝对是 str - 为什么要排除unicode?!

答案 2 :(得分:5)

不,这里的类型检查不是Pythonic。如果你不喜欢多种方法,另一个选择是坚持使用一种方法,但使用多个参数:

def find(name=None, employee_number=None):
    if sum(x != None for x in (name, employee_number)) != 1:
        #raise exception - exactly one value should be passed in
    if name is not None:
        #find employee by name and return
    if employee_number is not None:
        #find employee by employee number and return

使用时,意图与多种方法一样明显:

employee1 = x.find(name="John Smith")
employee2 = x.find(employee_number=90210)

答案 3 :(得分:2)

我会说是的,它是'Pythonic'并且有一些例子支持这个(其他海报没有给出)。要正确回答这个问题,应该有例子!

来自python核心:

  • string.startswith()它接受字符串或元组(字符串)。
  • string.endswith()

在pymongo:

  • find_one()接受要查找的dict对象,或者它将使用另一个其他对象作为id。

抱歉,我不知道更多,但我认为有很多方法的例子根据给定的参数表现不同。这是不强制执行类型之美的一部分。

答案 4 :(得分:1)

获得这种功能的更多pythonic方法是尝试以首选方式使用它(无论这可能意味着什么),如果参数不支持,请尝试替代方案。

这有两种方法:

class EmployeeCollection(object):
    def find(value):
        try:
            #find employee by name and return
        catch:
            try:
                #find employee by employee number and return
            catch:
                raise TypeError()

但那有点难过。这是我通常这样做的方式:

class EmployeeCollection(object):
    def find(value):
        if hasattr(value, 'join'):
            #find employee by name and return
        elif hasattr(value, '__div__'):
            #find employee by employee number and return
        else:
            raise TypeError()

实际上,我要检查的实际属性取决于这些注释中发生的情况,我更愿意检查我实际使用的属性。