我正在做一个项目,我需要一个采用任意 Python 对象的方法,如果该对象的行为类似于dict
、list
或tuple
- 意味着它支持通过键或索引访问集合成员的想法 -我的方法应该返回一个可以遍历对象的键值或索引值对的迭代器。如果迭代器简单地遍历对象键或索引,这对我的目的也很好。这是我到目前为止的代码:
from collections import Mapping, Sequence
# Tuple used to identify string-like objects in Python 2 or 3.
STRINGS = (str, unicode) if str is bytes else (str, bytes)
def get_keyval_iter(obj):
if isinstance(obj, STRINGS): return None
elif isinstance(obj, Sequence): return enumerate(obj)
elif isinstance(obj, Mapping): return getattr(obj, 'iteritems', obj.items)()
else: return None
# For example:
print list(get_keyval_iter([0, 11, 22])) # [(0, 0), (1, 11), (2, 22)]
print list(get_keyval_iter(dict(a = 1, b = 2))) # [('a', 1), ('b', 2)]
print [ get_keyval_iter("foobar") ] # [None]
print [ get_keyval_iter(1234) ] # [None]
我不喜欢这个解决方案有两个原因:(1)在一般原则上,我宁愿查询对象的接口而不是检查它的类型;(2) 我的代码将返回None
用户定义的类,这些类的对象未通过isinstance
测试,但仍然支持__getitem__
协议,并且理论上可以为我提供相关键或索引的迭代器。
这是我想写的代码:return obj.__getitemiter__()
-- 或类似的东西。
我是否忽略了一种明显的方式来获得我需要的东西——即,对任意对象的键或索引(或其键值或索引值对)的迭代器?