在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
答案 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