Использование самоанализа для поиска методов объекта, затем фильтрация - PullRequest
1 голос
/ 07 января 2012

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

class WidgetFrobber:
    def simpleFrobAttempt(widget, data):
        # fastest way, might not work
    def cleverFrobAttempt(widget, data):
        # fiddly, fast, and doesn't always work
    def boringFrobAttempt(widget, data):
        # works most of the time, often slow
    def desperateFrobAttempt(widget, data):
        # doesn't always work, pathetically slow

Имея это в виду, я хотел бы определить метод класса, который ищет методы с именем ^[a-z]+FrobAttempt$, составляет их список и пытается переключать виджеты, пока виджет не будет успешноfrobbed (с этого момента он должен перестать заботиться о других методах) или у него заканчиваются возможные методы.Поскольку это мой код, я могу убедиться, что все методы whateverFrobAttempt имеют одинаковые соглашения об именах и требуемые аргументы. лучше , если есть какой-то порядок в списке методов, так что сначала пробуются те, которые имеют лучшую среднюю скорость, но это приемлемо, если они предпринимаются в случайном порядке.

Есть ли вменяемый способ сделать это так, чтобы при добавлении новых weirdFrobAttempt методов их попытка выполнялась автоматически, или мне лучше просто поддерживать жестко закодированный список таких методов и выполнять итерации по нему?

1 Ответ

2 голосов
/ 08 января 2012

Мне нравится идея Свена иметь регистр. Это глупо, но если хранить глобальный список имен методов нормально, мы могли бы сделать что-то вроде этого:

FROB_METHOD_REGISTER = []
def frob_method(fn):
    def decorate_frob(fn):
        FROB_METHOD_REGISTER.add(fn.__name__)
        return fn
    return decorate_frob

class WidgetFrobber:
    def get_frob_methods(self):
        return [getattr(self, method) for method in FROB_METHOD_REGISTER]

    @frob_method
    def simpleFrobAttempt(widget, data):
        # fastest way, might not work
    @frob_method
    def cleverFrobAttempt(widget, data):
        # fiddly, fast, and doesn't always work
    @frob_method
    def boringFrobAttempt(widget, data):
        # works most of the time, often slow
    @frob_method
    def desperateFrobAttempt(widget, data):
        # doesn't always work, pathetically slow

так что тогда вы можете сделать

for method in my_widget_frobber.get_frob_methods():
    #do your thing

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

Вы могли бы использовать __dict__. например

[fn for name, fn in WidgetFrobber.__dict__.iteritems() if "FrobAttempt" in name]

даст вам набор методов, которые вы ищете, но я бы не рекомендовал бы использовать такие вещи, как __dict__, если есть способ создать код, который более понятен и не имеет доступа к python внутренности. И там почти всегда должно быть.

...