2017-02-20 138 views
1

設計類時,我發現在類方法中,每次調用類方法時都會調用重複的步驟。例如,Python - 使用類方法來裝飾其他類方法

class Queue(object): 
    def __init__(self): 
     self.connection = Connection() 

    def create(self, name): 
     self.probe = self.connection.plug() 
     self.probe.create(name) 
     self.probe.unplug() 

    def delete(self, name): 
     self.probe = self.connection.plug() 
     self.probe.delete(name) 
     self.probe.unplug() 

而且有很多方法需要類似的步驟來'插入'和'拔掉''探頭'。在這種設計中,我們需要在每次執行操作時「插入」並「拔下」「探針」。

因此,我正在考慮由裝飾者包裝這些函數,以使代碼看起來不那麼重複。

class Queue(object): 
    def __init__(self): 
     self.connection = Connection() 

    def _with_plug(self, fn): 
     def wrapper(*args, **kwargs): 
      self.probe = self.connection.plug() 
      fn(*args, **kwargs) 
      self.probe.unplug() 

    @_with_plug   
    def create(self, name): 
     self.probe.create(name) 

    @_with_plug 
    def delete(self, name): 
     self.probe.delete(name) 

但是這種策略是行不通的。我怎麼可以在類中使用方法來修飾其他方法來在調用方法之前和之後執行此類操作?

+0

什麼是「但這種策略是行不通的。」意思? – Carcigenicate

+0

看起來像使用方法作爲裝飾器 - 以代碼顯示 - 總是給出錯誤,說明參數的數量。我認爲這是我使用裝飾者的方式不正確。 –

回答

0

您應該在類體外定義裝飾器函數,並且裝飾器函數應該返回包裝函數以使其工作。例如:

def _with_plug(fn): 
    def wrapper(self, *args, **kwargs): 
     self.probe = self.connection.plug() 
     fn(self, *args, **kwargs) 
     self.probe.unplug() 
    return wrapper 


class Queue(object): 
    def __init__(self): 
     self.connection = Connection() 

    @_with_plug   
    def create(self, name): 
     self.probe.create(name) 

    @_with_plug 
    def delete(self, name): 
     self.probe.delete(name) 
1

好像有點糊塗參數對我說:

文件deco.py,說

def _with_plug(fn): # decorator takes exactly one argument, the function to wrap 
    print("wrapping", fn.__name__) 
    def wrapper(self, *args, **kwds): 
     print("wrapper called") 
     self.probe = [self.connection, ".plug()"] 
     fn(self, *args, **kwds) 
     self.probe.append(".unplug()") 
    return wrapper # decorator must return the wrapped function 


class Queue(object): 
    def __init__(self): 
     self.connection = "Connection()" 

    @_with_plug 
    def create(self, name): 
     self.probe.append("create(name)") 

    @_with_plug 
    def delete(self, name): 
     self.probe.append("delete(name)") 

檢查:

>>> import deco 
wrapping create 
wrapping delete 
>>> q = deco.Queue() 
>>> q.create("name") 
wrapper called 
>>> q.probe 
['Connection()', '.plug()', 'create(name)', '.unplug()'] 

觀察該裝飾功能被稱爲在定義待包裝函數的時間,即在類定義完成之前,並且在創建第一個實例之前很久。因此,您不能以您嘗試的方式引用self