Я работаю над проектом, где мне нужен метод, который принимает произвольный объект Python, и если этот объект действует как dict
, list
или tuple
, что означает, что он поддерживает идею доступа к членам коллекции через key или index - мой метод должен возвращать итератор, который может пересекать пары ключ-значение или пары индекс-значение. Это также было бы хорошо для моих целей, если итератор просто пересекал ключи или индексы объектов. Вот код, который я получил до сих пор:Как получить итератор по ключам/индексам произвольного объекта Python?
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__()
- или что-то в этом роде.
Я пропустил очевидный способ получить то, что мне нужно - а именно, итератор над ключами или индексами произвольного объекта (или над его парами ключ-значение или индекс-значение)?
@FMc: Итак, вы есть; моя точка зрения заключается в том, что любое итеративное значение должно поддерживать 'iter()'. –
@FMc: и 'enumerate()' on 'iter()' не работает? –
Есть * всегда * пределы того, что может быть достигнуто. Если объект не предоставляет все методы, которые должны быть распознаны как сопоставление, это последовательность, если только у нее нет метода '__getitem__'. Вот где это должно закончиться. –