2015-09-05 2 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 как атрибут объекта. Можно ли изменить декоратор на logpid, если он обнаруживает, что метод принадлежит к некоторому классу, и этот класс содержит атрибут pid?

Я пробовал:

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 

Но это не работает вообще. Не могли бы вы помочь мне?

РЕФЕРАТ:

Я хочу, чтобы иметь возможность вызывать атрибут pid из class где принадлежит метод (func) без прохождения self в качестве аргумента в обертке, потому что в этом случае было бы не работает для методов которые не входят в классы.

+0

Вы сказали, что это не работает. Вы имеете в виду, что вы получаете ошибку атрибута? Если нет, объясните пожалуйста. – KobeJohn

+0

@kobejohn Например, просто печать - print self.pid NameError: глобальное имя «я» не определено. Потому что декоратор не знает, что он будет использоваться для метода объекта. Он также может использоваться вне функции. –

ответ

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 пустыми и печатать args [0] .pid, если он существует.