1

由于缺乏维护动态类型代码的经验,我正在寻找处理这种情况的最佳方法:

(python 中的示例,但可以使用任何动态类型语言)

def some_function(object_that_could_be_a_list):
     if isinstance(object_that_could_be_a_list, list):
          for element in object_that_could_be_a_list:
              some_function(element)
     else:
          # Do stuff that expects the object to have certain properties 
          # a list would not have

我对此感到很不安,因为我认为一个方法应该只做一件事,而且我认为它没有应有的可读性。因此,我很想创建三个函数:第一个函数将获取任何对象并在其他两个函数之间“排序”,一个用于列表,另一个用于“简单”对象。再说一次,这会增加一些复杂性。

什么是这里最“可持续”的解决方案,以及保证易于维护的解决方案?对于那些我不知道的情况,python 中有没有成语?提前致谢。

4

4 回答 4

6

不要键入 check - 做你想做的事,如果它不起作用,它会抛出一个你可以捕获和管理的异常。

蟒蛇的口头禅是'请求宽恕,而不是许可'。类型检查需要额外的时间,大多数时候,它是没有意义的。在鸭式环境中它也没有多大意义 - 如果它有效,谁在乎它为什么是类型?当其他可迭代对象也可以工作时,为什么要将自己限制在列表中?

例如:

def some_function(object_that_could_be_a_list):
    try:
        for element in object_that_could_be_a_list:
            some_function(element)
    except TypeError:
        ...

这更具可读性,将在更多情况下工作(如果我传入任何其他不是列表的可迭代对象,则有很多)并且通常会更快。

请注意,您混淆了术语。Python 是动态类型的,但不是弱类型的。弱类型化意味着对象根据需要更改类型。例如,如果您添加一个字符串和一个 int,它会将字符串转换为一个 int 来进行加法。Python 不这样做。动态类型意味着您不为变量声明类型,它可能在某些时候包含一个字符串,然后是一个 int。

鸭子类型是一个术语,用于描述对象的使用而不关心它的类型。如果它像鸭子一样走路,像鸭子一样嘎嘎叫——它可能是一只鸭子。

现在,这是一般情况,如果您认为您的代码会比“正确”更频繁地获得“错误”类型的对象,那么您可能需要输入检查速度。请注意,这种情况很少见,最好避免过早优化。通过捕获异常来做到这一点,然后进行测试——如果你发现它是一个瓶颈,那么就进行优化。

于 2012-04-14T17:49:15.000 回答
2

我倾向于这样做,而不是递归地这样做:

def foo(x):
    if not isinstance(x, list):
        x = [x]
    for y in x:
        do_something(y)
于 2012-04-14T18:22:46.717 回答
2

一种常见的做法是通过对不同类型的输入使用不同的参数来实现多接口。

def foo(thing=None, thing_seq=None):
    if thing_seq is not None:
        for _thing in thing_seq:
            foo(thing=_thing)
    if thing is not None:
        print "did foo with", thing
于 2012-04-14T18:00:57.563 回答
1

在这种情况下,您可以使用装饰器使其更易于维护:

from mm import multimethod

@multimethod(int, int)
def foo(a, b):
    ...code for two ints...

@multimethod(float, float):
def foo(a, b):
    ...code for two floats...

@multimethod(str, str):
def foo(a, b):
    ...code for two strings...
于 2012-04-14T17:52:16.570 回答