使用内省来查找对象的方法,然后过滤

时间:2012-01-07 19:57:55

标签: python oop metaprogramming introspection

我的Python模块中有一个类可以使用小部件。它有几种方法可以做到这一点,但我不知道哪些方法(如果有的话)实际上会有效,我可能会想出以后新方法来取消小部件。而且,擦拭小部件可能很昂贵。所以我想让我的类的一个实例能够查看自己,找到它为frobbing小部件提供的所有方法,并开始尝试frob小部件直到它成功,此时它应该停止关心它还没有尝试过的方法。

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$的方法,列出它们,并尝试frob小部件,直到小部件被成功擦除(在它应该停止关心其他方法)或者用尽可能的方法。因为它是我的代码,所以我可以确保whateverFrobAttempt方法都具有相同的命名约定和必需的参数。如果对方法列表有一些排序,那么最好,以便首先尝试具有更好平均速度的那些,但如果以随机顺序尝试它们是可以接受的。

有没有一种理智的方法来做到这一点,当添加新的weirdFrobAttempt方法时,它们会被自动尝试,或者我最好只是维护这些方法的硬编码列表并迭代它? / p>

1 个答案:

答案 0 :(得分:2)

我喜欢sven关于注册的想法。这很麻烦,但是如果存储方法名称的全局列表是可以的,那么我们可以这样做:

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

不确定这是最好的还是最pythonic的方式,如果某些方法严格优于其他方法,我很想让装饰者使用某种优先级队列/排名架构。

可以使用__dict__。例如

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

会为您提供一系列您正在寻找的方法,但如果有一种方法可以构建更清晰且不具备的代码,我会建议使用__dict__之类的内容t访问python内部。几乎总是应该有。