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的答案中提到的潛在問題,它檢查未綁定方法的第一個參數是該類的一個實例。