2012-08-08 33 views
1

我有一個類,它有太多的方法。大多數方法需要一個參數(始終是相同的名稱) - 我需要將參數的類型更改爲其他參數,但還想接受參數的「舊」版本(並且raise a DeprecationWarning)。在類中修改多個方法的調用參數

編輯我們可以假設參數總是作爲關鍵字參數傳遞。

什麼是最乾的DRY這樣做的方法?

該彈在我腦海的第一個解決方案是這樣的:

def check_orc(orc): 
    if isinstance(Snaga, orc): 
     orc = convert_to_urukhai(orc) 
     raise DeprecationWarning("You should not be sending snaga to combat") 
    return orc 

class Warrior(): 
    def slash_orc(sword, shield, opponent): 
     opponent = check_orc(opponent) 
     ... 

    def hack_orc(warhammer, opponent): 
     opponent = check_orc(opponent) 
     ... 
+3

將最常用的參數添加到自我,這樣您就可以避免將所有方法都傳遞給 – avasal 2012-08-08 08:45:27

+2

,或者通過sed命令很難編輯您的源代碼。這不是乾的,但更易讀和可維護。 – fanlix 2012-08-08 08:59:24

+0

我不明白 - 當它是實例的外部實體時,如何將參數添加到'self'? – Kimvais 2012-08-08 09:41:08

回答

4

avasal的評論是正確的。然而,對於教育目的,這裏是一個裝飾實現你想要什麼:

from functools import wraps 

def convert_orc(f): 
    @wraps(f) 
    def wrapper(self, opponent, *args, **kwargs): 
     if isinstance(Snaga, orc): 
      raise DeprecationWarning(...) 
      return f(self, convert_to_urukhai(opponent), *args, **kwargs) 
     else: 
      return f(self, opponent, *args, **kwargs) 
    return wrapper 

class Warrior(): 
    @convert_orc 
    def slash_orc(self, opponent, sword, shield): 
     ... 

    @convert_orc 
    def hack_orc(self, opponent, warhammer): 
     ... 

注:我搬到opponent到參數中的第一位置

2

你能告訴我們,如果這始終是最後一個參數?如果沒有,你必須使用它的名字。

我的想法是這樣:

def check_orc(orc): 
    if isinstance(orc, int): 
     orc = str(orc) 
     print DeprecationWarning("You should not be sending snaga to combat") 
    return orc 

def check_opp(meth): 
    code = meth.func_code 
    argnames = code.co_varnames[:code.co_argcount] 
    if 'opponent' in argnames: 
     from functools import wraps 
     argidx = argnames.index('opponent') 
     @wraps(meth) 
     def replace(*a, **k): 
      if 'opponent' in k: 
       k['opponent'] = check_orc(k['opponent']) 
      else: 
       a = list(a) 
       a[argidx] = check_orc(a[argidx]) 
       a = tuple(a) 
      return meth(*a, **k) 
     return replace 
    else: 
     return meth 

class Warrior(): 
    @check_opp 
    def slash_orc(self, sword, shield, opponent): 
     print "slash", (sword, shield, opponent) 

    @check_opp 
    def hack_orc(self, warhammer, opponent): 
     print "hack", (warhammer, opponent) 

Warrior().slash_orc(1,3,4) 
Warrior().hack_orc(6,5) 
Warrior().slash_orc(1,3,opponent=4) 
Warrior().hack_orc(6,opponent=5) 
Warrior().slash_orc(1,3,"4") 
Warrior().hack_orc(6,"5") 
Warrior().slash_orc(1,3,opponent="4") 
Warrior().hack_orc(6,opponent="5") 

這是一個非常醜陋的黑客攻擊,但仍然應該工作,並從重新排序的參數爲您節省。

這裏我使用一種檢查來找到正確的參數並對其進行修改,而不管它是否已經作爲關鍵字或索引參數傳遞。

請注意,我稍微更改了測試以使其適用於我(我「棄用」整數並且需要strs)。你只需要我的check_opp()功能,並將其應用於任何你需要的地方。

+1

+1,但我已經看到更好看的代碼在brainf * ck :)這真是該死的醜陋! – 2012-08-08 09:10:58

+1

@JoelCornett是的,它是:-)但如果「對手」有時在這裏,有時在那裏,你幾乎沒有其他選擇... – glglgl 2012-08-08 09:16:05

+0

「對手」總是一個關鍵字參數(如果不是,我可以做它如此) – Kimvais 2012-08-08 09:42:35

相關問題