【问题标题】:Generate python methods from template requiring mere search/replace of string从只需要搜索/替换字符串的模板生成 python 方法
【发布时间】:2016-10-13 06:26:25
【问题描述】:

这些天我正在使用 ANTLR 来解析一些语言。我选择使用 Python。 ANTLR 生成的解析器类包含许多名称相似的方法:

class autogeneratedparser(xxx):
    def something_enter(self,ctx):
       pass
    def something_exit(self,ctx)
       pass

我通过定义一个继承类来覆盖这些

class myclass(autogeneratedparser)
    particularthing = False
    def particularthing_enter(self,ctx):
       print(ctx.name)
       myclass.particularthing = true
    def particularthing_exit(self,ctx):
       print(ctx.name)
       myclass.particularthing = false

我想动态地自动生成所有这些方法,包括更改它们各自的变量名。在伪代码中:

generate for particularthing in anything:
        $(particularthing) = False
        def $(particularthing)_enter(self,ctx):
           print(ctx.name)
           myclass.$(particularthing) = true
        def $(particularthing)_exit(self,ctx):
           print(ctx.name)
           myclass.$(particularthing) = false

我显然可以告诉 vim 这样做,但我确信 Python 也有办法,只是不知道怎么做 :-)

感谢您的宝贵意见 :)

【问题讨论】:

    标签: python dynamic methods lambda


    【解决方案1】:

    您需要做的就是遍历初始类的属性,只选择匹配SOMETHING_enterSOMETHING_exit 的那些,然后创建存根方法并将它们与type() (yes, it is used for creating dynamic classes) 放在一起。

    这是我的版本:

    # the generated class
    class SomeClass(object):
        def something_enter(self, ctx):
           pass
        def something_exit(self, ctx):
           pass
    
    
    def generate_stubbed_class(klass_name, klass):
        # creates and returns a function that does the generic behavior (print's out ctx.name)
        # and sets the attribute to the given value
        def generate_stub(name, value):
            def stub(self, ctx):
                print(ctx.name)
                setattr(self, name, value)
    
            return stub
    
        attributes = {}
    
        for name in dir(klass): # lists all attributes (names only)
            try:
                key, oper = name.split('_')
            except ValueError:
                # not in the format of SOMETHING_SOMETHING
                continue
    
            attr = getattr(klass, name)
    
            # make sure it's a function and name ends in _enter or _exit
            if callable(attr) and oper in ('enter', 'exit'):
                value = oper == 'enter' # True for 'enter', False for 'exit'
                attributes[name] = generate_stub(key, value)
                attributes[key] = False # set more than once, but no negative effect
    
        # this is where the magic happens
        return type(klass_name, (klass,), attributes)
    
    
    MyClass = generate_stubbed_class('MyClass', SomeClass)
    obj = MyClass()
    
    assert isinstance(obj, SomeClass)
    
    # need some class with a 'name' attribute, so we create one on the fly
    from collections import namedtuple
    Data = namedtuple('Data', 'name')
    
    # initially it's False
    assert obj.something is False
    
    # set to True, prints 'foo'
    obj.something_enter(Data('foo'))
    assert obj.something is True
    
    # back to False, prints 'bar'
    obj.something_exit(Data('bar'))
    assert obj.something is False
    

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 2010-11-14
      • 1970-01-01
      • 2020-01-06
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多