【问题标题】:elegant way of setting multiple methods to equal another method将多个方法设置为等于另一个方法的优雅方式
【发布时间】:2014-02-03 14:48:17
【问题描述】:

我在一个类中有这个方法:

def do_exit():
  # some task

我想将一堆其他方法分配给do_exit,所以目前我正在这样做:

do_quit = do_exit
do_stop = do_exit
do_finish = do_exit
do_complete = do_exit
do_leave = do_exit

这很好,但我想知道是否有更好的方法,特别是如果我要经常这样做的话。

【问题讨论】:

  • 这里讲了多少种方法?对于 5 个作业,这非常好
  • 很抱歉,这似乎是个不恰当的问题。但为什么这是一个问题?为什么不是简单的文档条目,有一个 do_exit 具有这样名称的方法。我对我可以调用 5 个不同的名字来完成相同任务的想法感到困惑。我真的很喜欢这个问题,因为这可以在 python 中以通用方式解决。但它甚至会适得其反,当一个地方看到do_finish 而在另一个地方看到do_quit,在相同的上下文中。通常不同的名称在相同的上下文中使用时意味着不同的任务。

标签: python methods assign


【解决方案1】:

您可以考虑制作一个字典来保存您的方法。使用 defaultdict,您可以确保调用 do_exit,如果在任何情况下都没有为特定的函数名称插入任何其他内容。另一方面,这可能不是很安全或经过验证,例如拼写错误:

from collections import defaultdict
method_dict = defaultdict(lambda: do_exit)

# Try this
method_dict["do_quit"]()

如果您愿意,还可以在一个类中覆盖__getattr__。假设,只是猜测,所有这些类型的方法都以do 开头,否则条件可能是它们以complete 的同义词结尾。您可以给类一个类属性,该属性包含适当的约定项并检查它们,并根据需要在method_dict 中查找它们。

from collections import defaultdict

class Foo(object):
    QUIT_WORDS = ['exit', 'quit', 'stop', 'finish', 'complete', 'leave']

    def __init__(self):
        self.method_dict = defaultdict(lambda: self.do_exit)

    def __getattr__(self, attr):
        if any([attr.endswith("_{}".format(x)) for x in self.QUIT_WORDS]):
            return self.method_dict[attr]
        else:
            return super(Foo, self).__getattribute__(attr)

    def do_exit(self):
        print "Exit!"

例如:

In [88]: f = Foo()

In [89]: f.do_quit()
Exit!

In [90]: f.do_exit()
Exit!

In [91]: f.do_go_bye_bye()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-91-2584940dee36> in <module>()
----> 1 f.do_go_bye_bye()

<ipython-input-87-3b0db0bf6a47> in __getattr__(self, attr)
     11             return self.method_dict[attr]
     12         else:
---> 13             return super(Foo, self).__getattribute__(attr)
     14 
     15 

【讨论】:

  • 很棒的解决方案。我对其进行了一些修改以适合我的用例。你能告诉我我的修改是否有任何可能的问题吗:ideone.com/Cjpcve 谢谢!
  • 看起来不错。如果它最终对您有用,请考虑投票和/或将答案标记为已接受。
【解决方案2】:

您的代码实际上很危险:如果您将初始类子类化,您将得到意想不到的行为。考虑以下几点:

class Foo(object):
    def m1(self):
        print "Hello!"

    m2 = m1


class Bar(Foo):
    def m1(self):
        print "World!"

# prints "World!", as expected
Bar().m1()

# prints "Hello!", because Bar.m2 is Foo.m2 is Foo.m1, *not* Bar.m1
Bar().m2()

不幸的是,唯一简单您的用例不破坏继承的解决方案是手动定义每个方法,使用def foo(self): return self.bar() 类型的构造。

【讨论】:

  • 我不明白这有什么误导或危险?如果这不是所需的行为,请不要这样做。另一方面,如果一个人认为设置类属性在子类的上下文中被“重新解释”,那只是一个不正确的假设——而不是“危险”地尝试拥有一系列的类方法,这些方法都归结为同样的方法。
【解决方案3】:

你可以这样做:

do_quit = do_stop = do_finish = do_complete = do_leave = do_exit

【讨论】:

  • 对不起,我不认为这有什么不同。 OP 想要别的东西。
猜你喜欢
  • 2011-06-01
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-16
  • 1970-01-01
相关资源
最近更新 更多