2015-09-05 98 views
0

我为了记录目的而构建了一个小装饰器。检查方法是否是类方法和调用属性

def func_detail(func): 
    def func_wrapper(*args,**kwargs): 
     log(func.__name__+' ARGS: {}'.format(str(args))) 
     return func(*args,**kwargs) 
    return func_wrapper 

这适用于对象方法和普通方法。我想在多线程中使用它。我有一个包含pid作为对象属性的类。如果它检测到该方法属于某个类并且此类包含属性pid,是否可以将修饰器更改为logpid

我已经试过:

def func_detail(func): 
    def func_wrapper(*args,**kwargs): 
     log('PID: '+self.pid if self.pid is not None else ' '+func.__name__+' ARGS: {}'.format(str(args))) 
     return func(*args,**kwargs) 
    return func_wrapper 

但这并不是在所有工作。你可以帮帮我吗?

摘要

我希望能够调用从那里方法(func)所属的class属性pid没有传球self作为参数传递给包装,因为在这种情况下它不会工作的方法这些不在类内。

+0

你说这行不通。你的意思是你得到一个属性错误?如果没有请解释。 – KobeJohn

+0

@kobejohn例如只是打印 - 打印self.pid NameError:全局名称'self'未定义这是因为装饰器不知道它将用于对象方法。它也可以用于函数之外。 –

回答

3

方法的参数self不会在您的装饰器中神奇地提供给您的func_wrapper函数。相反,它将成为您用*args捕获的头寸参数中的第一个。如果您想使用它,您需要检查args[0]并查看它是否具有pid属性。

试试这个,检查先说第一个参数存在,那么,如果它有一个pid属性:

log('{}FUNC: {} ARGS: {}'.format('PID: {} '.format(args[0].pid) 
           if args and hasattr(args[0], "pid") else '', 
           func.__name__, args)) 
0

如果你调用一个方法,对象本身将是第一个参数,该self在方法实现中。

如果您的修饰器仅适用于方法(定义为def methodName(self, ...):),则可以在自己中捕获第一个参数。

然后,您可以尝试打印self.pid并在没有任何此类属性时捕获异常。由于自由函数和方法之间几乎没有区别,我认为你应该为自由函数定义两个装饰器,另一个为方法定义,或者定义一个装饰器参数来表示它是否是方法。

另一种解决方法是检查参数是否不为空,如果存在,则输出args [0] .pid。