【问题标题】:Generate dynamic methods in a class在类中生成动态方法
【发布时间】:2012-01-30 11:02:41
【问题描述】:

我想要一个带有动态方法的类。

从这些数组中:

prefix = ['android','iphone','blackberry'] 
method = ['AddToPush','DelFromPush','GetPushMessages']

我想创建一个类:

class MobileManager(object)

    def __init__(self):
        self.mobileLib = MobileLib()

    def androidAddToPush(self, args):
        self.mobileLib.AddToPush(args, 'android')

    def iphoneAddToPush(self, args):
        self.mobileLib.AddToPush(args, 'iphone')    

    def blackberryAddToPush(self, args):
        self.mobileLib.AddToPush(args, 'blackberry') 

   [...]

如何在运行时生成/创建这些方法?

【问题讨论】:

    标签: python python-2.7 code-generation


    【解决方案1】:

    如果您的一组前缀/方法是在初始化时定义的,您可以尝试这样的操作:

    class MobileManager(object):
        def __init__(self):
            for prefix_name in prefix:
                for method_name in method:
                    func = lambda self, args: getattr(self.mobileLib, method_name)(args, prefix)
                    full_method_name = "%s%s" % (prefix, method_name)
                    setattr(self, full_method_name, func)
            ...
    

    如果您的动态方法变得更加复杂,那么 lambda 很快就会受到限制。

    【讨论】:

    • 会这样工作吗:self.mobileLib.method_name(args, prefix)?
    • 在你的代码中你有一行:func = lambda self, args: self.mobileLib.AddToPush(args, prefix) 'AddToPush' 应该来自方法数组。
    • 它不起作用: 1. 从func() 参数中删除self(你将它绑定到一个具体实例,而不是一个类)。 2. 所有func 将使用method_name 的最后一个值。 You don't want that.
    • setattr(self, prefix+method_name, make_func(getattr(self.mobileLib, method_name), prefix)) 应该修复它,make_func = lambda func, prefix: lambda args: func(args, prefix)
    • 这个正在工作! make_func = lambda func, prefix_name: lambda args: func(args, prefix_name) setattr(self, prefix_name+method_name, make_func(getattr(self.mobileLib, method_name), prefix_name)) 非常感谢!
    【解决方案2】:

    或者为什么不继承

    class MobileManager(object)
    
        def __init__(self):
            self.mobileLib = MobileLib()
    
        def AddToPush(self, args, platform=None):
            self.mobileLib.AddToPush(args, platform)
    
    class Android(MobileManager):
        def __init__(self):
            MobileManager.__init__(self)
    
        def AddToPush(self, args):
             MobileManager.AddToPush(args, platform="android")
    

    【讨论】:

      【解决方案3】:

      动态方法通常是导致混淆代码的错误方法。

      在这里,我会这样做:

      class Mobile(object):
          def add_to_push(self, args):
              ....
          def del_from_push(self, args):
              ...
          def get_push_methods(self, args):
              ...
      

      在你的经理中:

      class MobileManager(object):
          def __init__(self):
              self.android = Mobile()
              self.blackberry = Mobile()
              self.iphone = Mobile()
      

      现在,你可以写manager.android.add_to_push(args),而不是manager.mobileLib.add_to_push(args, 'android')

      如果您有平台变量,您甚至可以动态调度:getattr(manager, platform).add_to_push(args)

      如果您希望 3 种类型的平台具有不同的行为,您可以创建 Mobile 的子类(可能是 AndroidMobile、BlackberryMobile 和 iPhoneMobile)。

      当出现新平台(可能是 windows7)时,如何更改代码以支持它是显而易见的。

      【讨论】:

        猜你喜欢
        • 2018-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多