2015-03-02 63 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装饰检查时,类被装饰。