2017-10-16 196 views
1

我想寫所有非魔法方法的類修飾器來裝飾這些方法。這個想法是,所有類的方法在打電話後打印它的名字;我不想裝飾所有的方法,但只有階級。裝飾者log_method的作品。我有問題log_class裝飾。沒有錯誤,也沒有輸出。修飾所有方法的類的裝飾器

import traceback 
import inspect 

def log_method(func): 
    def inner(*args, **kwargs): 
     print("{}{}".format(int(len(traceback.extract_stack())/2) * " ", func.__name__)) 

     return func(*args, **kwargs) 

    return inner 

def log_class(cls): 
    for m in dir(cls): 
     if not m.startswith("__") and inspect.isfunction(getattr(cls, m)): 
      m = log_method(m) 
      print(m) 
    return cls 

@log_class 
class Cls: 
    def __init__(self): 
     pass 

    def A(self): 
     self.B() 

    def B(self): 
     self.C() 

    def C(self): 
     pass 


Cls().A() 
""" 
Excepted output: 
A 
B 
    C 
""" 
+1

'm = log_method(m)'只是給變量'm'賦值'log_method'的返回值,它根本不影響類。 –

回答

3

你應該重新綁定方法使用setattr傳遞方法的名稱m類對象;像你所做的那樣分配給當地名稱m,什麼都不做。

更進一步說,您目前正在將一個字符串m傳遞給log_method。相反,你應該通過getattr取回後傳遞給函數對象本身:

def log_method(func): 
    def inner(*args, **kwargs): 
     print("{}{}".format(int(len(traceback.extract_stack())/2) * " ", func.__name__)) 
     return func(*args, **kwargs) 
    return inner 

def log_class(cls): 
    for m in dir(cls): 
     if not m.startswith("__") and inspect.isfunction(getattr(cls, m)): 
      setattr(cls, m, log_method(getattr(cls, m))) # here 
    return cls 

Cls.A() 
# A 
# B 
# C 

PS:log_method從不用於裝飾,所以它不是一個裝飾。

+1

不錯。現在用元類來做。 ;) –

+0

@ PM2Ring拋出一個元類,並且答案變成一個漩渦,如果OP沒有以前的經驗,那麼更有可能是這樣:) –