1

我想在本地范围内将类的方法作为函数(装饰后)公开。例如,如果我有一个类和装饰:如何在Python中自动公开和装饰函数版本的方法?

def some_decorator(f): 
    ...transform f... 
    return decorated_f 

class C(object): 
    def __init__(self,x): 
     self.x = x 
    def f(self,y): 
     "Some doc string" 
     return self.x + y 
    def g(self,y,z): 
     "Some other doc string" 
     return self.x + y + z 

,如果我不关心automizing的过程中,我可以在下面的代码添加到我的模块如下:

@some_decorator 
def f(C_instance,x): 
    "Some doc string." 
    return C_instance.f(x) 

@some_decorator 
def g(C_instance,x,y): 
    "Some other doc string." 
    return C_instance.g(x,y)  

的效果以下评估为真

c = C(0) 
f(c,1) == c.f(1) 

但我希望能够自动做到这一点。像这样的:

my_funs = expose_methods(MyClass) 
for funname, fun in my_funs.iteritems(): 
    locals()[funname] = some_decorator(fun) 

foo = MyClass(data) 
some_functionality(foo,*args) == foo.some_functionality(*args) 

会做的伎俩(虽然它感觉有点错误这样声明局部变量)。我怎样才能做到这一点,使方法的所有相关属性正确转换为函数版本?我将不胜感激任何建议。

P.S.

我知道我可以装饰类实例的方法,但这并不是我所追求的。它更多的是(1)对函数版本语法的偏好(2)我的装饰器使函数映射超过对象的集合,并且花哨和优化的方式。通过装饰方法获取行为(2)需要我的集合类从它们包含的对象继承属性,这与对集合语义是正交的。

+0

修改由'locals()'返回的字典是未定义的。我想知道你为什么在这里使用'locals()'而不是'globals()'。据我所知,这些功能应该是在模块的全局范围内。 – 2012-02-29 19:34:56

回答

2

您是否知道可以直接使用未绑定的方法?

obj.foo(arg)相当于ObjClass.foo(obj, arg)

class MyClass(object): 
    def foo(self, arg): 
     ... 

obj = MyClass() 
print obj.foo(3) == MyClass.foo(obj, 3) # True 

参见Class method differences in Python: bound, unbound and staticdocumentation

+0

哈哈,是的。好吧,我想我不知道。或者,也许我做了,但深入到这个问题,我没有意识到这个简单的解决方案。谢谢。 – 2012-02-29 20:10:44

+0

@GabrielMitchell:如果您使用的是Python 2.x,您应该意识到这种未绑定方法的第一个参数必须是“MyClass”类型,这可能会影响传递'MyClass'实例的集合。 (不过你可以定义一个魔术装饰器来改变这种行为。) – 2012-02-29 20:15:24

+0

@SvenMarnach是的,我在2.7。我的一个装饰器解析参数以查找相关集合的实例,作为确定实际调用的一部分。有没有什么特别的关于3.x会消除这种需要? – 2012-02-29 20:45:21

0

你说你对函数语法有偏好。你可以在班级之外定义你所有的方法,而且他们会按你的意愿工作。

class C(object): 
    def __init__(self,x): 
     self.x = x 

def f(c,y): 
    "Some doc string" 
    return c.x + y 
def g(c,y,z): 
    "Some other doc string" 
    return c.x + y + z 

如果你希望他们在类为好,你随时可以:

for func in f, g: 
    setattr(C, func.__name__, func) 

或者与当地人的反省,而不是函数名自省:

for name in 'f', 'g': 
    setattr(C, name, locals()[name]) 

还是没有反省,这可以说是更简单和更容易管理,除非你有相当多的这些方法/功能:

C.f = f 
C.g = g 

这还可以避免在关于Python检查codeape的答案中提到的潜在问题,它检查未绑定方法的第一个参数是该类的一个实例。