Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 优雅地处理不同的参数类型_Python - Fatal编程技术网

Python 优雅地处理不同的参数类型

Python 优雅地处理不同的参数类型,python,Python,我有一个函数,在最简单的情况下,它对一系列的项进行操作 def foo(items): for item in items: # do stuff 有时,我不想直接向它传递iterable of items,而是希望传递一个提供获取iterable的方法的对象: def foo(obj): for item in obj.iteritems(): # do same stuff as above import collections isins

我有一个函数,在最简单的情况下,它对一系列的项进行操作

def foo(items):
    for item in items:
        # do stuff
有时,我不想直接向它传递iterable of items,而是希望传递一个提供获取iterable的方法的对象:

def foo(obj):
    for item in obj.iteritems():
        # do same stuff as above
import collections
isinstance(obj, collections.Iterable)
我可以这样合并这两个案例:

def foo(obj):
    try:
        items = obj.iteritems()
    except ValueError:
        items = obj
    for item in items:
        # do stuff
def foo(objs):
    for item in itertools.chain.from_iterable(obj.iteritems() for obj in objs):
        # do same stuff again
这个很好用。现在我得到了第三个用例,如下所示:

def foo(obj):
    try:
        items = obj.iteritems()
    except ValueError:
        items = obj
    for item in items:
        # do stuff
def foo(objs):
    for item in itertools.chain.from_iterable(obj.iteritems() for obj in objs):
        # do same stuff again

我仍然可以使用
try-except
方法,因为接口不兼容。但是,嵌套的try-catch将开始变得非常丑陋。当我想添加第四个用例时,情况就更糟了。有没有办法在不嵌套
try
-块的情况下解决此问题?

要检查对象是否可编辑:

def foo(obj):
    for item in obj.iteritems():
        # do same stuff as above
import collections
isinstance(obj, collections.Iterable)
这会帮你解决一些问题

此外,处理此类问题的一种方法是使用递归性(但不知道它是否适用):


目前,您可能至少应该在这里使用两种方法,第三种方法只是使用
itertools.chain.from\u iterable
结果调用第一种方法。您还可能使用*args;这取决于你的具体情况(提供一个真实的例子是有帮助的)。还可以使用简单的helper函数返回正确类型的迭代器

也许这可以解决:

def _foo_iter(obj):
    try:
        return obj.iteritems()
    except AttributeError:
        return obj

def foo(*objs):
    for obj in objs:
        for item in _foo_iter(obj):
hasattr(对象、名称)

如果hasattr(对象,'.'uuuu iter'):
返回[o代表obj中的o]
埃利夫·哈斯塔特(obj,“iteritems”):
返回[o代表对象中的o.iteritems()]
elif isinstance(对象,列表)或isinstance(对象,元组):
返回[o.iteritems()表示对象中的o[o表示对象中的o]]
其他:
提高打字错误
分类栏(列表):
定义iteritems(自我):
返回自我
打印foo([1,2,3])
打印foo(Bar([1,2,3]))
打印foo([[1,2,3],[1,2,3]]
印刷字体(1)
[1, 2, 3]
[1, 2, 3]
[[1, 2, 3], [1, 2, 3]]
回溯(最近一次呼叫最后一次):
文件“test.py”,第20行,在
印刷字体(1)
文件“test.py”,第11行,在foo中
提高打字错误
打字错误

必须同意克里斯的观点:魔法理解一切输入都会反过来咬你。如果您将一个对象的iterable和一个iterable的iterable传递给它,那么如何指定在什么级别开始实际处理数据


最好坚持使用“列表或生成器”作为输入,然后预处理对函数的调用。

啊,我真希望Python中有适当的函数重载@André:几乎总是在Python中,如果您想要那种函数/方法重载,那么您的做法是错误的。但是显式发送iterable有什么问题?太冗长了?是的。所有的用例都是同样频繁的,其中有些只是太冗长了。@Chris:是的,差不多了。我几乎总能找到更好的选择;-)我见过太多Python类使用
addfoo()
addbar()
addmeh()
方法来避免在单个
add()
方法中进行运行时类型检查!我提供的代码与真实代码非常接近,只是名称发生了更改。@Space\u C0wb0y:但您没有解释您使用它的准确程度和用途。对于某些事情,可能有一种更好的方法没有出现在您身上(这种情况经常发生,例如,在一个问题中,我使用了一个自定义函数,而
x in y
也可以,但由于某种原因,我没有想到)该函数是一个生成器,用于计算每个项目的特定属性。@Space\u C0wb0y:仔细考虑,我认为这实际上正是您所需要的,除非您真的想要
foo([a,b,c])
,而不是
foo(a,b,c)
,用于您的链案例。通过使用*args,它被放入一个列表中,因此您可以在objs中为obj使用
。不管它是否正是您想要的-帮助函数应该是您所需要的,以使代码不那么混乱。@Chris:我也这么认为。感谢您的建议。
hasattr
本质上只是一个
try
round
getattr
@chris No,它不强制嵌套异常,例如它更具可读性。这就是问题所在。