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

发布于 2024-12-25 17:36:49 字数 931 浏览 3 评论 0原文

我的 Python 模块中有一个用于 frobs 小部件的类。它有多种方法可以做到这一点,但我事先不知道哪些方法(如果有的话)会真正起作用,并且我可能会在以后找到新的方法来获取小部件。此外,fbbing 小部件可能会很昂贵。因此,我希望我的类的一个实例能够查看自身,找到它用于 frobing 小部件的所有方法,并开始尝试 frob widgets 直到成功,此时它应该停止关心尚未尝试过的方法。

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

有了这个,我想定义一个类的方法,它查找名为 ^[az]+FrobAttempt$ 的方法,创建它们的列表,并尝试 frob 小部件,直到小部件被成功排除(此时它应该停止关心其他方法)或者它耗尽了可能的方法。由于这是我的代码,我可以确保 whateverFrobAttempt 方法都具有相同的命名约定和所需参数。最好对方法列表进行一些排序,以便首先尝试平均速度较好的方法,但如果以随机顺序尝试它们也是可以接受的。

有没有一种明智的方法可以做到这一点,这样当添加新的 weirdFrobAttempt 方法时,它们将被自动尝试,或者我最好只维护此类方法的硬编码列表并对其进行迭代?

I have a class in my Python module that frobs widgets. It has several ways to do this, but I don't know ahead of time which ones, if any, will actually work, and I might figure out new ways to frob the widgets later. Also, frobbing widgets can be expensive. So I'd like to have an instance of my class be able to look at itself, find all of the methods that it has for frobbing widgets, and to start trying to frob widgets until it succeeds, at which point it should stop caring about the methods it hasn't yet tried.

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

With that in place, I'd like to define a method of the class that looks for methods named ^[a-z]+FrobAttempt$, makes a list of them, and tries to frob widgets until the widget is successfully frobbed (at which point it should stop caring about other methods) or it runs out of possible methods. Since it's my code, I can make sure that the whateverFrobAttempt methods all have the same naming conventions and required arguments. It's best if there's some ordering to the list of methods, so that the ones with a better average speed get tried first, but it's acceptable if they're attempted in random-ish order.

Is there a sane way to do this such that when new weirdFrobAttempt methods are added, they'll be tried automatically, or am I better off just maintaining a hardcoded list of such methods and iterating over that ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愚人国度 2025-01-01 17:36:49

我喜欢斯文关于拥有寄存器的想法。这是很hacky,但是如果存储方法名称的全局列表是可以的,那么我们可以做这样的事情:

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__之类的东西。不访问 python 内部。而且几乎总是应该有。

I like sven's idea of having a register. This is hacky, but if storing a global list of method names is ok then we could do something like this:

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

so then you can do

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

Not sure if this is the best or most pythonic way, and I'd be tempted to make the decorator use some sort of priority queue/ranking schema if there are some methods that are strictly better than others.

You could use __dict__. for example

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

would give you the set of methods you are looking for, but I would not recommend using things like __dict__ if there is a way to build code that is more clear and doesn't access python internals. And there almost always should be.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文