【问题标题】:Is there a "wildcard method" in Python?Python中有“通配符方法”吗?
【发布时间】:2016-04-12 13:29:30
【问题描述】:

我正在寻找一种方法来使用未在该类中定义但动态处理的类的方法。举个例子,我想实现的是从

class Hello:
    def aaa(self, msg=""):
        print("{msg} aaa".format(msg=msg))

    def bbb(self, msg=""):
        print("{msg} bbb".format(msg=msg))

if __name__ == "__main__":
    h = Hello()
    h.aaa("hello")
    h.bbb("hello")

# hello aaa
# hello bbb

可以在类中使用aaabbb(和其他)而无需显式定义它们。对于上面的示例,这将是一个构造,它接收所用方法的名称(例如aaa)并相应地格式化消息。

换句话说,一种“通配符方法”,它本身会处理其名称并根据名称执行条件操作。在伪代码中(复制上面的例子)

def *wildcard*(self, msg=""):
    method = __name__which__was__used__to__call__me__
    print("{msg} {method}".format(msg=msg, method=method))

这样的结构可能吗?

【问题讨论】:

    标签: python class methods


    【解决方案1】:

    你可以重载类的__getattr__方法:

    class Hello:
        def __getattr__(self, name):
            def f(msg=""):
                print("{} {}".format(msg, name))
            return f
    
    if __name__ == "__main__":
        h = Hello()
        h.aaa("hello")
        h.bbb("hello")
    

    结果:

    hello aaa
    hello bbb
    

    【讨论】:

      【解决方案2】:

      如果您事先知道方法的名称,则可以使用为您添加所有方法的装饰器来完成此操作。

      from functools import partial
      
      def glue(f, names=[]):
          def wrapper(cls):
              method = getattr(cls,f)
              for name in names:
                  setattr(cls, name, partial(method,name=name))
              return cls
          return wrapper
      

      像这样使用它:

      @glue(f = 'wildcard', names = ['aaa', 'bbb'])
      class Hello():
          def wildcard(self, msg='', name=''):
              print("{} {}".format(msg, name))
      

      如果你不熟悉装饰器,上面的@ 语法相当于在类定义之后这样做:

      Hello = glue(f = 'wildcard', names = ['aaa', 'bbb'])(Hello)
      

      【讨论】:

        【解决方案3】:

        我发现上面的答案有点难以理解,所以我这样做了。

        受到 Django 代码的启发。

        class MyClass:
            def __init__(self, **kwargs):
        
                for arg in ('aaa', 'bbb'):
                    # generate a new function based on the template function.
                    setattr(self, f'make_{arg}', partialmethod(self._make_ARG, arg=arg))
        
            def _make_ARG(self, arg, **kwargs):
                value = getattr(self, arg)
                # override make_{ARG} function to generate an argument based on codex.
                return value
        

        【讨论】:

        • 这假设 aaabbb 是已知的(事实并非如此,它应该处理任何方法名称)
        猜你喜欢
        • 1970-01-01
        • 2021-09-20
        • 2015-05-13
        • 1970-01-01
        • 2012-09-15
        • 1970-01-01
        • 2013-05-29
        • 2023-04-08
        • 2019-01-02
        相关资源
        最近更新 更多