Я не помню, спал ли я или нет, но, кажется, я помню, что была функция, которая позволяла что-то вроде:
foo in iter_attr(array of python objects, attribute name)
Я просмотрел документы, но такого рода вещи не подпадают ни под какие очевидные перечисленные заголовки
Использование понимания списка создаст временный список, который может поглотить всю вашу память, если искомая последовательность велика. Даже если последовательность не велика, создание списка означает итерацию по всей последовательности, прежде чем in
можно будет начать ее поиск.
Временного списка можно избежать, используя выражение генератора:
foo = 12
foo in (obj.id for obj in bar)
Теперь, пока он находится obj.id == 12
в начале bar
, поиск будет быстрым, даже если он bar
будет бесконечно долгим.
Как предложил @Matt, рекомендуется использовать, hasattr
если в каком-либо из объектов bar
может отсутствовать id
атрибут:
foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
Вы хотите получить список объектов, которые имеют определенный атрибут? Если это так, понимание списка является правильным способом сделать это.
result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
Вы всегда можете написать один самостоятельно:
def iterattr(iterator, attributename):
for obj in iterator:
yield getattr(obj, attributename)
будет работать со всем, что повторяется, будь то кортеж, список или что-то еще.
Я люблю python, он делает такие вещи очень простыми и не более хлопотными, чем необходимые, а в использовании такие вещи невероятно элегантны.
Нет, вы не мечтали. В Python есть отличная система понимания списков, которая позволяет довольно элегантно манипулировать списками, и в зависимости от того, чего именно вы хотите достичь, это можно сделать несколькими способами. По сути, то, что вы делаете, говорит «Для элемента в списке, если критерий. Соответствует», и из этого вы можете просто перебрать результаты или вывести результаты в новый список.
Я собираюсь привести пример из Dive Into Python , потому что он довольно элегантный, и они умнее меня. Здесь они получают список файлов в каталоге, а затем фильтруют список для всех файлов, которые соответствуют критериям регулярного выражения.
files = os.listdir(path) test = re.compile("test\.py$", re.IGNORECASE) files = [f for f in files if test.search(f)]
Вы можете сделать это без регулярных выражений, для вашего примера, для всего, что ваше выражение в конце возвращает true для совпадения. Есть и другие варианты, такие как использование функции filter (), но если бы я собирался выбирать, я бы пошел с этим.
Эрик Сиппл
Функция, о которой вы думаете, вероятно operator.attrgettter
. Например, чтобы получить список, содержащий значение атрибута «id» каждого объекта:
import operator
ids = map(operator.attrgetter("id"), bar)
Если вы хотите проверить, содержит ли список объект с идентификатором == 12, то аккуратный и эффективный (т.е. не повторяющий весь список без необходимости) способ сделать это:
any(obj.id == 12 for obj in bar)
Если вы хотите использовать 'in' с attrgetter, сохраняя при этом ленивую итерацию списка:
import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)
То, о чем я думал, может быть достигнуто с использованием списочных представлений, но я подумал, что есть функция, которая делает это немного аккуратнее.
то есть 'bar' - это список объектов, каждый из которых имеет атрибут 'id'
Мифический функциональный путь:
foo = 12
foo in iter_attr(bar, 'id')
Способ понимания списка:
foo = 12
foo in [obj.id for obj in bar]
В ретроспективе, способ понимания списка довольно опрятен в любом случае.
Если вы планируете поискать что-либо удаленно приличного размера, лучше всего использовать словарь или набор. В противном случае вам, по сути, придется перебирать каждый элемент итератора, пока не дойдете до нужного.
Если это не обязательно чувствительный к производительности код, тогда должен работать способ понимания списка. Но обратите внимание, что это довольно неэффективно, потому что он перебирает каждый элемент итератора, а затем снова переходит назад, пока не найдет то, что хочет.
Помните, Python имеет один из самых эффективных алгоритмов хеширования. Используйте это в ваших интересах.
Думаю:
#!/bin/python
bar in dict(Foo)
Это то, что вы думаете. При попытке увидеть, существует ли определенный ключ в словаре в python (хэш-таблица в python), есть два способа проверить. Первый - это has_key()
метод, прикрепленный к словарю, а второй - пример, приведенный выше. Он вернет логическое значение.
Это должно ответить на ваш вопрос.
А теперь немного не по теме, чтобы связать это с ранее полученным ответом о понимании списка (для большей ясности). Постижения списка создают список из базового цикла for с модификаторами. В качестве примера (чтобы уточнить) способ использования in dict
языковой конструкции в понимании списка :
Скажем, у вас есть двумерный словарь, foo
и вам нужны только словари второго измерения, которые содержат ключ bar
. Относительно простым способом сделать это было бы использование списка со следующим условием:
#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])
Обратите внимание if bar in value
на то, что в конце оператора ** это модифицирующее предложение, которое сообщает списку, что следует сохранять только те пары ключ-значение, которые соответствуют условию. ** В этом случае baz
это новый словарь, который содержит только словари из foo. которые содержат строку (Надеюсь, я ничего не пропустил в этом примере кода ... возможно, вам придется взглянуть на документацию по пониманию списка, найденную в руководствах docs.python.org и на secnetix.de , оба сайта являются хорошими ссылками, если у вас есть вопросы в будущем.).