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

StackOverflow https://stackoverflow.com/questions/683

  •  08-06-2019
  •  | 
  •  

Вопрос

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

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 есть довольно отличная система понимания списков, которая позволяет вам довольно элегантно манипулировать списками, и в зависимости от того, чего именно вы хотите достичь, это можно сделать несколькими способами.По сути, то, что вы делаете, это говорите "Для элемента в списке, если criteria.matches", и исходя из этого, вы можете просто выполнить итерацию по результатам или выгрузить результаты в новый список.

Я собираюсь привести пример из Погрузитесь в 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() метод, прикрепленный к словарю, и второй - это пример, приведенный выше.Он вернет логическое значение.

Это должно дать ответ на ваш вопрос.

А теперь немного отклонимся от темы, чтобы связать это с понимание списка ответ был дан ранее (для большей ясности). Перечислите Основные понятия создайте список из базового для цикла с модификаторами.В качестве примера (чтобы немного прояснить ситуацию) приведен способ использования 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, оба сайта являются хорошими ссылками, если у вас возникнут вопросы в будущем.).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top