Получить экземпляр класса, в котором определенное свойство имеет определенное значение

1

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

Но в любом случае. Мне интересно, есть ли (квази) встроенный способ поиска определенного экземпляра класса, который имеет свойство, установленное на определенное значение.

Пример:

class Klass(object):
    def __init__(self, value):
        self.value = value
    def square_value(self):
        return self.value * self.value

 >>> a = Klass(1)
 >>> b = Klass(2)
 >>> instance = find_instance([a, b], value=1)
 >>> instance.square_value()
 1
 >>> instance = find_instance([a, b], value=2)
 >>> instance.square_value()
 4

Я знаю, что я мог бы написать функцию, которая будет проходить через все экземпляры Klass и возвращает те, которые были запрошены. С другой стороны, эта функциональность выглядит так, как будто она должна существовать в Python уже, а если нет, то должны быть очень веские причины, почему это не так. Другими словами, то, что я пытаюсь сделать здесь, может быть сделано гораздо лучше.

(И, конечно, я не ищу способ квадратизировать значение. Вышеприведенный пример - только пример конструкции, которую я пытаюсь найти).

  • 0
    Это очень расплывчато. Не могли бы вы объяснить, чего вы пытаетесь достичь? Может быть, добавить код?
  • 0
    что есть что ...
Показать ещё 3 комментария
Теги:
class

2 ответа

4
Лучший ответ

Использовать фильтр:

filter(lambda obj: obj.value == 1, [a, b])

Фильтр вернет список объектов, отвечающих указанному вами требованию. Документы: http://docs.python.org/library/functions.html#filter

Bascially, filter(fn, list) выполняет итерацию по list и применяет fn к каждому элементу. Он собирает все элементы, для которых fn возвращает true, помещает их в список и возвращает их.

NB: фильтр всегда будет возвращать список, даже если есть только один объект, который соответствует. Поэтому, если вы только хотели вернуть первый экземпляр, который соответствует, вам придется что-то вроде:

def find_instance(fn, objs):
    all_matches = filter(fn, objs)
    if len(all_matches) == 0:
        return False # no matches
    else:
        return all_matches[0]

или, еще лучше,

def find_instance(fn, objs):
    all_matches = filter(fn, objs)
    return len(all_matches) > 0 and all_matches[0] # uses the fact that 'and' returns its second argument if its first argument evaluates to True. 

Затем вы вызываете эту функцию следующим образом:

instance = find_instance(lambda x: x.value == 1, [a, b])

и тогда instance будет a.

2

Более эффективная версия ответа Ord, если вы ищете только один соответствующий экземпляр, будет

def find_instance(fn, objs):
    all_matches = (o for o in objs if fn(objs))
    return next(all_matches, None)

instance = find_instance(lambda x: x.value == 1, [a, b])

Это остановит поиск, как только вы найдете первое совпадение (хорошо, если ваша тестовая функция стоит дорого или большой список) или None если нет совпадений.

Обратите внимание, что next функция является новой в Python 2.6; в более старой версии, я думаю, вам нужно сделать

try:
   return all_matches.next()
except StopIteration:
   return None

Конечно, если вы просто делаете это один раз, вы можете сделать это как однострочный:

instance = next((o for o in [a, b] if o.value == 1), None)

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

  • 2
    Код Дугала является примером выражения генератора (обратите внимание, как он заключил o for o in ... бит с () вместо []. Это не создает предварительно список совпадений, а просто создает инструкции о том, как построить список. Когда вы говорите next(matches, None) , Python начинает выполнять инструкции, но останавливается, когда генерирует первое соответствие. (Вы можете получить больше совпадений, повторно вызывая next ()). Бит None основном сообщает генератор должен вернуть None, если совпадений нет. Документы для выражений генератора: docs.python.org/tutorial/classes.html#generator-expressions

Ещё вопросы

Сообщество Overcoder
Наверх
Меню