Python:即时重命名方法名称 [英] Python: renaming method names on-the-fly

查看:43
本文介绍了Python:即时重命名方法名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有许多文件使用具有以下语法的类:

I have many files using classes with the following syntax:

o = module.CreateObject()
a = o.get_Field

现在实现已从"get_XXX"和"set_XXX"更改为"XXX":

and now the implementation has changed from 'get_XXX' and 'set_XXX' to just 'XXX':

o = module.CreateObject()
a = o.Field

此实现是一个外部程序包,我不想更改.是否可以编写一个包装程序,该包装程序将即时拦截对"get_XXX"的所有调用,然后替换为对新名称"XXX"的调用?

This implementation is an external package, which I don't want to change. Is it possible to write a wrapper which will on-the-fly intercept all calls to 'get_XXX' and replace then with calls to the new name 'XXX'?

o = MyRenamer(module.CreateObject())
a = o.get_Field   # works as before, o.Field is called
a = o.DoIt()      # works as before, o.DoIt is called

它需要拦截所有调用,而不仅仅是拦截有限的字段,根据方法名称决定是否修改它,并导致调用具有修改名称的方法.

It needs to intercept all calls, not just to a finite-set of fields, decide based on the method name if to modify it and cause a method with a modified name to be called.

推荐答案

如果要继续在已切换为使用属性的对象上使用 get_Field set_Field (您只需访问或分配给 Field ),就可以使用包装器对象:

If you want to continue to use get_Field and set_Field on an object that has switched to using properties (where you simply access or assign to Field), it's possible to use an wrapper object:

class NoPropertyAdaptor(object):
    def __init__(self, obj):
        self.obj = obj

    def __getattr__(self, name):
        if name.startswith("get_"):
            return lambda: getattr(self.obj, name[4:])
        elif name.startswith("set_"):
            return lambda value: setattr(self.obj, name[4:], value)
        else:
            return getattr(self.obj, name)

如果您使用额外的语法(例如,对对象进行索引或迭代),或者需要使用 isinstance 来识别对象的类型,则会出现问题.

This will have problems if you are using extra syntax, like indexing or iteration on the object, or if you need to recognize the type of the object using isinstance.

更复杂的解决方案是创建一个重写名称的子类,并强制对象使用它.这并不是完全包装,因为外部代码仍将直接处理对象(因此魔术方法和 isinstance )将按预期工作.这种方法适用于大多数对象,但是对于花哨的元类魔术不断出现的类型以及某些内置类型而言,它可能会失败:

A more sophisticated solution would be to create a subclass that does the name rewriting and force the object to use it. This isn't exactly a wrapping, since outside code will still deal with the object directly (and so magic methods and isinstance) will work as expected. This approach will work for most objects, but it might fail for types that have fancy metaclass magic going on and for some builtin types:

def no_property_adaptor(obj):
    class wrapper(obj.__class__):
        def __getattr__(self, name):
            if name.startswith("get_"):
                return lambda: getattr(self, name[4:])
            elif name.startswith("set_"):
                return lambda value: setattr(self, name[4:], value)
            else:
                return super(wrapper, self).__getattr__(name)

    obj.__class__ = wrapper
    return obj

这篇关于Python:即时重命名方法名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆