Использование 'in' для сопоставления атрибута объектов Python в массиве

Я не помню, спал ли я или нет, но, кажется, я помню, что была функция, которая позволяла что-то вроде:

foo in iter_attr(array of python objects, attribute name)

Я просмотрел документы, но такого рода вещи не подпадают ни под какие очевидные перечисленные заголовки

3.08.2008 13:19:16
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'))
41
11.09.2008 22:42:14

Вы хотите получить список объектов, которые имеют определенный атрибут? Если это так, понимание списка является правильным способом сделать это.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
12
3.08.2008 15:59:19

Вы всегда можете написать один самостоятельно:

def iterattr(iterator, attributename):
    for obj in iterator:
        yield getattr(obj, attributename)

будет работать со всем, что повторяется, будь то кортеж, список или что-то еще.

Я люблю python, он делает такие вещи очень простыми и не более хлопотными, чем необходимые, а в использовании такие вещи невероятно элегантны.

10
27.08.2008 20:13:49

Нет, вы не мечтали. В 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 (), но если бы я собирался выбирать, я бы пошел с этим.

Эрик Сиппл

7
24.11.2011 09:57:27

Функция, о которой вы думаете, вероятно 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)

6
5.02.2011 08:10:41

То, о чем я думал, может быть достигнуто с использованием списочных представлений, но я подумал, что есть функция, которая делает это немного аккуратнее.

то есть 'bar' - это список объектов, каждый из которых имеет атрибут 'id'

Мифический функциональный путь:

foo = 12
foo in iter_attr(bar, 'id')

Способ понимания списка:

foo = 12
foo in [obj.id for obj in bar]

В ретроспективе, способ понимания списка довольно опрятен в любом случае.

5
3.08.2008 16:13:29

Если вы планируете поискать что-либо удаленно приличного размера, лучше всего использовать словарь или набор. В противном случае вам, по сути, придется перебирать каждый элемент итератора, пока не дойдете до нужного.

Если это не обязательно чувствительный к производительности код, тогда должен работать способ понимания списка. Но обратите внимание, что это довольно неэффективно, потому что он перебирает каждый элемент итератора, а затем снова переходит назад, пока не найдет то, что хочет.

Помните, Python имеет один из самых эффективных алгоритмов хеширования. Используйте это в ваших интересах.

3
27.08.2008 20:30:22

Думаю:

#!/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 , оба сайта являются хорошими ссылками, если у вас есть вопросы в будущем.).

0
3.08.2008 15:47:22