Общий итератор по значениям (а не по ключам) любого итерируемого
Существует ли общий способ получения итератора, который всегда перебирает значения (желательно, хотя он может работать и итерацию ключей тоже) из словарей или других итерируемых элементов (списки, множества...)?
Позвольте мне уточнить: когда вы выполняете "iter(list)
"вы получаете итератор для значений (не для индексов, которые звучат очень похоже на" ключ "в словаре), но когда вы делаете"iter(dict)
"Вы получаете ключи.
Есть ли инструкция, атрибут... что угодно..., которое всегда перебирает значения (или ключи) итерируемого, независимо от того, какой это тип итерируемого?
У меня есть код с методом "добавления", который должен принимать несколько различных типов итерируемых типов, и единственное решение, которое мне удалось найти, это что-то вроде этого:
#!/usr/bin/python2.4
class Sample(object):
def __init__(self):
self._myListOfStuff = list()
def addThings(self, thingsToAdd):
myIterator = None
if (isinstance(thingsToAdd, list) or
isinstance(thingsToAdd, set) or
isinstance(thingsToAdd, tuple)):
myIterator = iter(thingsToAdd)
elif isinstance(thingsToAdd, dict):
myIterator = thingsToAdd.itervalues()
if myIterator:
for element in myIterator:
self._myListOfStuff.append(element)
if __name__ == '__main__':
sample = Sample()
myList = list([1,2])
mySet = set([3,4])
myTuple = tuple([5,6])
myDict = dict(
a= 7,
b= 8
)
sample.addThings(myList)
sample.addThings(mySet)
sample.addThings(myTuple)
sample.addThings(myDict)
print sample._myListOfStuff
#Outputs [1, 2, 3, 4, 5, 6, 7, 8]
Я не знаю... Это выглядит немного... неуклюже для меня
Было бы здорово получить общий итератор для подобных случаев, поэтому я мог бы написать что-то вроде...
def addThings(self, thingsToAdd):
for element in iter(thingsToAdd):
self._myListOfStuff.append(element)
... если итератор всегда давал значения, или...
def addThings(self, thingsToAdd):
for element in iter(thingsToAdd):
self._myListOfStuff.append(thingsToAdd[element])
... если итератор вернул ключи (я знаю, что концепция ключа в наборе является своего рода "особой", поэтому я бы предпочел перебирать значения, но все же... возможно, он мог бы вернуть хэш сохраненного значения).
Есть ли такая вещь в Python? (Я должен использовать Python2.4, кстати)
Спасибо всем заранее
3 ответа
Большинство коллекций не имеют понятия или "ключи" или "ценности". Они просто хранят предметы, и перебирая их, вы получаете эти предметы. Только отображения (dict-лайки) предоставляют "ключи" и "значения". И способ их итерации по умолчанию использует ключи, потому что for x in collection: assert x in collection
должен быть инвариантом (и (key, value) in d
редко имеет смысл, в отличие от key in d
). Таким образом, нет способа перебирать только значения, потому что у наименьших коллекций есть вещи, называемые "значениями".
Однако вы можете игнорировать ключи в отображениях. Поскольку вы должны использовать Python 2.4, использование ABC не вызывает вопросов... Боюсь, самый простой способ будет:
def iter_values(it):
if hasattr(it, 'itervalues'):
return it.itervalues()
return iter(x)
Который может все еще сломаться, но обрабатывает диктовки и подобные сопоставления.
Я не знаю ничего встроенного, что делает это. Я полагаю, вы могли бы сделать что-то вроде:
def itervalues(x):
if hasattr(x, 'itervalues'): return x.itervalues()
if hasattr(x, 'values'): return iter(x.values())
return iter(x)
То, что вы ищете, это dict.items()
метод, который возвращает (ключ, значение) кортежи. Вот пример использования:
d = {'a': 1, 'b': 2, 'c': 3}
for k, v in d.items():
print "key:", k, "- value:", v
Который, как вы можете себе представить, будет выводить
key: a - value: 1
key: b - value: 2
key: c - value: 3
Изменить: если вы хотите получить реальный итератор, а не просто последовательность, вы также можете использовать dict.iteritems()
метод, который работает так же.
Edit2: кажется, я неправильно понял ваш вопрос, так как вы, кажется, просите универсальную функцию, которая будет работать с любой итерацией, забудьте мой ответ;-)