2015-03-02 59 views
0

我試圖檢索裝飾的@classmethod中的導入字符串以在管道系統中註冊此字符串。但是當我在裝飾器函數中檢查函數對象時,找不到關於類對象或類名的任何信息。從裝飾類方法檢索導入字符串

因此,代碼看起來是這樣的:

def import_string_decorator(**opt_kwargs): 

    def wrap(f): 

     # Here is the problem 
     if inspect.ismethod(f): 
      class_name = f.im_self.__name__ 
      import_string = f.__module__ + "." class_name + "." + f.__name__ 
      # But this doesn't work because f no longer is a <bound method to class 'SomeClass'> but is a regular <function> 
     else: 
      import_string = f.__module__ + "." + f.__name__ 

     # Register the string 
     do_something(import_string, **opt_kwargs) 

     def wrapped_f(*args, **kwargs): 

      f(*args, **kwargs) 

     return wrapped_f 

    return wrap 


# Decorated Class 
opt_dict = {"some": "values"} 

class SomeClass(object): 

    @classmethod 
    @import_string_decorator(**opt_dict) 
    def double_decorated_function(cls, *args, **kwargs): 

     pass 

但我還沒有找到一種方法來檢索裝飾功能的類對象。 inspect.ismethod()函數也返回False,因爲它檢查底下的isinstance(types.MethodType)

+1

在**類對象構建之前,就會發生裝飾**。當時沒有什麼課程可以發現。 – 2015-03-02 14:20:08

+0

當您將函數名稱作爲類或實例的屬性進行訪問時,會發生綁定類方法(或任何其他方法)。 Python綁定* late *,並且動態地執行,而不是在您定義要用作方法的函數時。 – 2015-03-02 14:21:23

回答

1

你想要的東西不能用函數裝飾器來完成。在創建類對象之前創建並裝飾函數對象。 Python首先執行類體,然後結果名稱形成類屬性。

隨着您使用descriptor protocol訪問作爲屬性的名稱,動態地進行方法的綁定。

您需要爲創建類創建鉤子才能訪問類名;你可以使用類裝飾器,或者使用元類。如果這使得它更容易,您可以使用函數裝飾結合這些技術:

@registered_class 
class SomeClass(object): 

    @classmethod 
    @import_string_decorator(**opt_dict) 
    def double_decorated_function(cls, *args, **kwargs): 
     pass 

其中import_string_decorator可以註釋功能(可以設置它的屬性,例如)爲registered_class裝飾檢查時,類被裝飾。