Использование 'in' для сопоставления атрибута объектов Python в массиве
Я не помню, спал ли я или нет, но, кажется, я помню, что была функция, которая позволяла что-то вроде:
foo in iter_attr(array of python objects, attribute name)
Я просмотрел документы, но такого рода вещи не подпадают под какие-либо очевидные перечисленные заголовки
8 ответов
Использование понимания списка создаст временный список, который может поглотить всю вашу память, если искомая последовательность велика. Даже если последовательность не велика, построение списка означает повторение всей последовательности до 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 есть отличная система понимания списков, которая позволяет довольно элегантно манипулировать списками, и в зависимости от того, чего именно вы хотите достичь, это можно сделать несколькими способами. По сути, то, что вы делаете, говорит: "Для элемента в списке, если attribute.matches", и из этого вы можете просто перебрать результаты или вывести результаты в новый список.
Я собираюсь привести пример из 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, содержащие строку bar (надеюсь, я ничего не пропустил в этом примере кода... возможно, вам придется взглянуть на документацию по пониманию списка, найденную в руководствах docs.python.org и на secnetix.de оба сайта являются хорошими ссылками, если у вас есть вопросы в будущем.).