python:子类一个元类

Mic*_*zny 1 python metaclass

为了将各种类的方法放入全局注册表,我正在使用带有元类的装饰器.装饰器标签,元类将函数放在注册表中:

class ExposedMethod (object):
    def __init__(self, decoratedFunction):
        self._decoratedFunction = decoratedFunction

    def __call__(__self,*__args,**__kw):
        return __self._decoratedFunction(*__args,**__kw)

class ExposedMethodDecoratorMetaclass(type):
    def __new__(mcs, name, bases, dct):
        for obj_name, obj in dct.iteritems():
            if isinstance(obj, ExposedMethod):
                WorkerFunctionRegistry.addWorkerToWorkerFunction(obj_name, name)
        return type.__new__(mcs, name, bases, dct)

class MyClass (object):
    __metaclass__ = DiscoveryExposedMethodDecoratorMetaclass

    @ExposeDiscoveryMethod
    def myCoolExposedMethod (self):
        pass
Run Code Online (Sandbox Code Playgroud)

我现在已经到了需要两个功能注册表的地步.第一个想法是将元类子类化并将其他注册表放入其中.为此,方法只需要重写.

由于重写意味着冗余代码,这不是我真正想要的.因此,如果有人能够指定如何将属性放入元类中的方法,那么在执行new时可以读取该元素会很好.有了这个,可以放入正确的注册表,而无需重写新的.

Ale*_*lli 5

你的ExposedMethod实例不像普通的实例方法那样行事,而是像静态方法一样 - 事实上你给其中一个self参数暗示你不知道这一点.您可能需要向类添加一个__get__方法以ExposedMethod使其成为描述符,就像函数对象一样 - 有关描述符的更多信息,请参阅此处.

但是有一种简单的方法,因为函数可以具有属性......:

def ExposedMethod(registry=None):
    def decorate(f):
        f.registry = registry
        return f
    return decorate
Run Code Online (Sandbox Code Playgroud)

并且在装饰器中(比元类更简单!需要Python 2.6或更高版本 - 在2.5或更早版本中你需要坚持使用元类或在class语句后显式调用它,尽管答案的第一部分和功能下面的代码仍然很好):

def RegisterExposedMethods(cls):
    for name, f in vars(cls).iteritems():
        if not hasattr(f, 'registry'): continue
        registry = f.registry
        if registry is None:
            registry = cls.registry
        registry.register(name, cls.__name__)
    return cls
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做:

@RegisterExposedMethods
class MyClass (object):

    @ExposeMethod(WorkerFunctionRegistry)
    def myCoolExposedMethod (self):
        pass
Run Code Online (Sandbox Code Playgroud)

等等.这很容易扩展到允许暴露的方法有几个注册表,从类中获取默认注册表(它可以在类装饰器中,例如,如果这对你更好)避免陷入与元类陷入而不会丢失任何功能.事实上,这也正是为什么类装饰在Python 2.6中引入:他们可以利用的地方,90%左右的元类的实际应用,并有很多不是自定义元类的简单.