2015-05-22 21 views
3

這是一種最佳實踐問題。覆蓋python中方法的內部函數

我有一個定義了一些方法的類結構。在某些情況下,我想覆蓋方法的特定部分。首先想到的是將我的方法分解爲更多的原子片段並覆蓋下面的相關部分。

class myTest(object): 
    def __init__(self): 
     pass 

    def myfunc(self): 
     self._do_atomic_job() 
     ... 
     ... 

    def _do_atomic_job(self): 
     print "Hello" 

這是一個實用的方法來解決問題。但是由於我有太多的參數需要傳輸到_do_atomic_job(),並且我不想傳遞和檢索大量的參數。其他選項是將這些參數設置爲self.param_var等的類變量,但這些參數僅用於代碼的一小部分,使用self不是我首選的解決方法。

最後一個選項我認爲是使用內部函數。 (我知道我會在變量的作用域問題,但正如我所說,這是一個最好的做法,不理會他們,認爲範圍和有關內部函數的所有事情都按預期工作)

class MyTest2(object): 
    mytext = "" 

    def myfunc(self): 
     def _do_atomic_job(): 
      mytext = "Hello" 
     _do_atomic_job() 
     print mytext 

讓我們假設作品如預期。我想要做的是覆蓋內部函數_do_atomic_job()

class MyTest3(MyTest2): 
    def __init__(self): 
     super(MyTest3, self).__init__() 
     self.myfunc._do_atomic_job = self._alt_do_atomic_job # Of course this do not work! 

    def _alt_do_atomic_job(self): 
     mytext = "Hollla!" 

難道我想達到什麼是壓倒一切的繼承類的方法的內在功能_do_atomic_job

這可能嗎?

回答

3

無論是將_do_atomic_job()轉換成適當的方法,還是將 轉化爲自己的類似於最佳方法。覆蓋內部函數 不能工作,因爲您將無法訪問包含方法的本地變量。你說_do_atomic_job()需要很多參數返回很多值。也許你組一些參數到合理的目標:

_do_atomic_job(start_x, start_y, end_x, end_y) # Separate coordinates 
_do_atomic_job(start, end)      # Better: start/end points 
_do_atomic_job(rect)       # Even better: rectangle 

如果你不能做到這一點,並_do_atomic_job()是合理的自包含的, 您可以創建輔助類AtomicJobParamsAtomicJobResult。 一個例子使用namedtuples代替類:

AtomicJobParams = namedtuple('AtomicJobParams', ['a', 'b', 'c', 'd']) 

jobparams = AtomicJobParams(a, b, c, d) 
_do_atomic_job(jobparams)    # Returns AtomicJobResult 

最後,如果微小作業是自包含的,你甚至可以因素其加入 自己的類AtomicJob

class AtomicJob: 
    def __init__(self, a, b, c, d): 
     self.a = a 
     self.b = b 
     self.c = c 
     self.d = d 
     self._do_atomic_job() 

    def _do_atomic_job(self): 
     ... 
     self.result_1 = 42 
     self.result_2 = 23 
     self.result_3 = 443 

總體而言,這似乎更像是一個代碼因子分解問題。目標是在適當的情況下將工作委託給助手的相當類似的 類。按照single responsibility principle。如果值屬於一起,則將它們捆綁在一個值類中。

正如戴維·米勒(一個著名的Linux內核開發者)recently said

如果你寫超過4個或5個功能參數的接口,它是 可能是你,我不能成爲朋友。

+0

使用'namedtuples'看起來不錯。使用助手類看起來更漂亮,因爲它允許我將代碼拆分成類內的較小部分。 – FallenAngel

0

內部變量與它們被定義的位置相關,而不是它們被執行的位置。這打印出「你好」。

class MyTest2(object): 
    def __init__(self): 
     localvariable = "hello" 
     def do_atomic_job(): 
      print localvariable 
     self.do_atomic_job = do_atomic_job 

    def myfunc(self): 
     localvariable = "hollla!" 
     self.do_atomic_job() 


MyTest2().myfunc() 

所以我看不出你可以使用局部變量沒有通過他們,這可能是做到這一點的最好辦法任何辦法。

注意:通過locals()會給你一個變量的字典,但這被認爲是相當不好的風格。

+0

謝謝,但是使用'locals()'對我來說也不合邏輯。同樣''do_atomic_job()'會做比印刷東西更多的東西,所以它也會是一個複雜的代碼。 – FallenAngel

+0

然後你有一些風格的感覺:)。像基督教艾辛格說,它可能需要一些返工。國際海事組織(IMO)的名爲「三元組」(triplet)只是在地毯下清除問題而且我對課堂沒有任何意見。尋找像Rectangle這樣的合理抽象類會很好,但是如果它只是用它來訪問init參數並且在函數調用中看起來更小,那麼我會質疑它的用處。我相信如果這是一個有價值的課程,可以添加一些有意義的方法。 – Ariakenom

+0

是的,它不是絕對的解決方案,所以我會期待更好的方法(: – FallenAngel