在Python中输入演绎

时间:2017-10-03 05:55:50

标签: python

在Python中是否有更好的方法来确定函数参数是单个数字还是数字列表。目前我正在使用异常的副作用来控制流量,但它看起来并不优雅:

def buildPattern( NumberOrList, Framework ):
    FinalPattern = '-->'
    try:
        ListLen = len(NumberOrList)
        #if this is a list, program flow will reach this point
        I = 0
        for Char in Framework:
            if Char == 'x':
                FinalPattern = FinalPattern + ' ' + str(NumberOrList[I])
                I = (I+1) % ListLen
            else:
                FinalPattern = FinalPattern + '  '
    except:
        #if we reach this point, we don't have a list... (or some other problem)
        for Char in Framework:
            if Char == 'x':
                FinalPattern = FinalPattern + ' ' + str(NumberOrList)
            else:
                FinalPattern = FinalPattern + '  '
    return FinalPattern

print buildPattern( 3,'x x x x x x x x ' ) #single number call
print buildPattern( [1,3,5], 'x x x x x x x x ' ) #list call

3 个答案:

答案 0 :(得分:6)

可以使用异常处理来执行此操作,但正如您所说,它不是很优雅。此外,如果经常引发异常,效率也不高,使用显式测试会更快。

实际上,重新设计代码会更优雅。 ;)只是因为Python允许你定义一个函数,其中arg可以是数字或列表并不意味着它是一个好主意。正如您所发现的那样,它往往会使函数的内部逻辑变得更加复杂,并且通常会导致不同执行路径中的重复代码。但无论如何......

测试arg的简洁方法是查看它是否是可迭代的,并且可以使用collections.Iterable类来执行此操作。在现代版本的Python中,该类已移至collections.abc模块,但它目前仍在collections中可用,以便更容易编写在Python 2&上正确运行的代码; Python 3。

顺便说一句,使用"裸体"通常不是一个好主意。 except。你应该总是列出你想要捕获的例外,否则你最终可能会捕捉到你不期望的东西,并且你的代码无法正确处理。

此外,遵循PEP-0008 style guide是一个好主意。它使其他人更容易阅读您的代码。

这是函数的更紧凑版本,使用PEP-0008样式名称编写。它使用itertools.cycle来简化源数据的循环。它还将输出字符串收集到列表和列表中。将它们连接在一起。这比在循环中进行字符串连接更有效。此代码在Python 2和Python 3上都能正确运行。

from __future__ import print_function
from collections import Iterable
from itertools import cycle

def build_pattern(source, framework):
    if not isinstance(source, Iterable):
        source = [source]
    source = cycle(map(str, source))
    final_pattern = ['-->']
    for char in framework:
        final_pattern.append(next(source) if char == 'x' else ' ')
    return ' '.join(final_pattern)

print(build_pattern(3, 'x x x x x x x x ')) #single number call
print(build_pattern([1, 3, 5], 'x x x x x x x x ')) #list call
print(build_pattern('abcde', 'x x x x x x x x ')) #string call

<强>输出

--> 3   3   3   3   3   3   3   3  
--> 1   3   5   1   3   5   1   3  
--> a   b   c   d   e   a   b   c  

正如VPfB在评论中提到的那样,字符串是可迭代的,所以如果你将一个字符串传递给我的build_pattern,它将直接传递给cycle(map(str, source)),它不会被包裹起来一个列表。这在这里相当不错,但有些情况下这种行为会导致问题,经典案例是任意嵌套列表的扁平化。答案here显示了如何处理这种情况。

答案 1 :(得分:3)

你为什么不试试这个

def buildPattern(NumberOrList, Framework):
    if isinstance(NumberOrList, list):
       # This is list
    else:
       # This is number

这是pep-8 python样式指南推荐的,而不是类型(obj)

<强>参考

https://www.python.org/dev/peps/pep-0008/#programming-recommendations

答案 2 :(得分:0)

只需在函数顶部使用带有isinstance的if语句:

if isinstance(NumberOrList, int):
    # Its a number
elif isinstance(NumberOrList,list):
    # Its a list
else:
    # Its something you dont want