我有一个函数,在最简单的情况下,它可以在一个可迭代的项目上运行。
def foo(items):
for item in items:
# do stuff
有时候,我不想直接传递一个可迭代的项目,而是一个提供获取可迭代项的方法的对象:
def foo(obj):
for item in obj.iteritems():
# do same stuff as above
我可以合并这两个案例:
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
- 块?
答案 0 :(得分:2)
按照目前的情况,你应该在这里使用至少两种方法,第三种只用itertools.chain.from_iterable
结果调用第一种方法。你也可以使用* args;这取决于你的确切情况(提供一个真实的例子是有帮助的)。您还可以使用简单的辅助函数来返回正确类型的迭代器。
也许这可能会成功:
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):
答案 1 :(得分:1)
必须同意克里斯:神奇的理解 - 一切输入都会转过来咬你。如果你传递一个可迭代的迭代对象的可迭代对象,你如何指定实际开始处理数据的级别?
最好坚持使用“列表或生成器”作为输入,然后预处理对函数的调用。
答案 2 :(得分:0)
检查对象是否可迭代:
import collections
isinstance(obj, collections.Iterable)
这可以让你摆脱一些问题。
此外,处理此类问题的一种方法是使用递归(不知道它是否适用):
def foo(obj):
if isinstance(obj, collections.Iterable):
for el in obj:
foo(el)
# now do stuff
答案 3 :(得分:0)
hasattr(object, name)
if hasattr(obj, '__iter__'):
return [o for o in obj]
elif hasattr(obj, 'iteritems'):
return [o for o in obj.iteritems()]
elif isinstance(obj, list) or isinstance(obj, tuple):
return [o.iteritems() for o in [o for o in obj]]
else:
raise TypeError
class Bar(list):
def iteritems(self):
return self.__iter__()
print foo([1,2,3])
print foo(Bar([1,2,3]))
print foo([[1,2,3], [1,2,3]])
print foo(1)
[1, 2, 3]
[1, 2, 3]
[[1, 2, 3], [1, 2, 3]]
Traceback (most recent call last):
File "test.py", line 20, in <module>
print foo(1)
File "test.py", line 11, in foo
raise TypeError
TypeError