2012-05-10 67 views
1

我很好奇裝飾器是如何工作的,所以看到它是否適用於將通用函數放在走路徑中。我想在路徑下的空間分隔文件中返回最長的整數段(然後返回該值或可能打印它)。這可能嗎?在Python中使用裝飾器的步行路徑

我試圖在countL中返回的東西沒有成功。然後很好奇,如果我放在外面的功能如何這將工作。裝飾者只能用於打印,還是可以從他們返回以獲得此示例以正確操作?

def walkPath(fn): 
    def wrapper(*args, **kwargs): 
     outside = None 
     for dirname, dirnames, filenames in os.walk(args[0]): 
      for filename in filenames: 
       fn(filename, dirname, outside, *args, **kwargs) 
    return wrapper 

@walkPath 
def countL(filename, dirname, outside, path, extension = '.wrd'): 
    if (filename[-4:] == extension): 
     with open(os.path.join(dirname, filename), 'r') as input: 
      data = input.readlines() 
     for i in range(len(data)): 
      temp = data[i].split() 
      if (int(temp[1]) - int(temp[0]) > longest):     
       outside = int(temp[1]) - int(temp[0]) 

這說明我在做什麼,而不裝飾,然後只是看到如果你能得到相同的功能,但使它通用。這意味着它不一定是一組文件中最長的單詞,但可能是文件名中帶有單詞「s」的一組文件。只是不知道如何正確處理外部變量最長的時間,或者如果裝飾器可能的話。

def countLength(path, extension = '.wrd'): 
    longest = 0 
    for dirname, dirnames, filenames in os.walk(path): 
     for filename in filenames: 
      if (filename[-4:] == extension): 
       with open(os.path.join(dirname, filename), 'r') as input: 
        data = input.readlines() 
       for i in range(len(data)): 
        temp = data[i].split() 
        if (int(temp[1]) - int(temp[0]) > longest): 
         longest = int(temp[1]) - int(temp[0]) 
    return longest 
+1

但你實際上並沒有在'wrapper'中返回任何東西...... – uhz

+1

你不會在'countL'中返回任何東西... – mgilson

+0

我試圖提供一個有用的例子,但我不能告訴你實際上是想從這個問題。我想你應該給出一個或兩個目錄結構的例子,其中的文件和你想要生成的輸出。 – senderle

回答

1

你的問題是,你正在試圖分裂成外循環和它的身體,但在循環中有本地變量(longest)比較數字。所以你需要做的是讓你的內部函數聚合結果。這意味着walkPath循環將需要將每個呼叫的結果保存到fn並將其交給下一個呼叫,因此您可以在fn內執行比較。最後,它應該吐出最後一次呼叫返回的內容。我想這就是你想用outside來做的事情。我還從countL中刪除了path參數,因爲它沒有做任何事情。例如,您應該像這樣工作:

def walkPath(fn): 
    def wrapper(outside, *args, **kwargs): 
     for dirname, dirnames, filenames in os.walk(args[0]): 
      for filename in filenames: 
       outside = fn(outside, filename, dirname, *args, **kwargs) 
     return outside 
    return wrapper 

@walkPath 
def countL(outside, filename, dirname, extension = '.wrd'): 
    if (filename[-4:] == extension): 
     with open(os.path.join(dirname, filename), 'r') as input: 
      data = input.readlines() 
     for i in range(len(data)): 
      temp = data[i].split() 
      if (int(temp[1]) - int(temp[0]) > outside):     
       outside = int(temp[1]) - int(temp[0]) 
    return outside 

你將不得不調用像countL(0)

+0

這工作,但我確實需要的路徑,因爲我把它作爲arg [0]傳遞給包裝函數。我更新了這個例子,效果很好。乾杯 –

0

您必須決定想要聚合的位置以及如何返回數據。我會做這種方式:

def walkPath(fn): 
    def wrapper(walkroot, *args, **kwargs): 
     for dirname, dirnames, filenames in os.walk(walkroot): 
      for filename in filenames: 
       res = fn(filename, dirname, *args, **kwargs) 
       if res is not None: yield res 
    return wrapper 

@walkPath 
def countL(filename, dirname, extension='.wrd'): 
    if os.path.splitext(filename)[1] == extension: 
     with open(os.path.join(dirname, filename), 'r') as input: 
      data = input.readlines() 
     for i in range(len(data)): 
      temp = data[i].split() 
      return int(temp[1]) - int(temp[0]) 

現在的walkPath()呼叫者得到一個發電機,產生從每個文件「差值」。所以,你可以很容易地找到max(walkPath(...))

除了最大值,我改變了擴展比較

if os.path.splitext(filename)[1] == extension: 

只要你import os地方。


停止。重新讀取代碼後,我必須問:

您是否有可能在文件中有多個值對?如果是這樣,我們必須使countL()返回一個發電機。

@walkPath 
def countL(filename, dirname, extension='.wrd'): 
    if os.path.splitext(filename)[1] == extension: 
     with open(os.path.join(dirname, filename), 'r') as input: 
      data = input.readlines() 
     for i in range(len(data)): 
      temp = data[i].split() 
      yield int(temp[1]) - int(temp[0]) 

現在裝飾countL()返回發生器產生的發電機,所以我們要做的

max(value for filegen in countL(...) for value in filegen) 

或者,我們可以改變walkPath()

def walkPath(fn): 
    def wrapper(walkroot, *args, **kwargs): 
     for dirname, dirnames, filenames in os.walk(walkroot): 
      for filename in filenames: 
       for item in fn(filename, dirname, *args, **kwargs): 
        yield item 
    return wrapper 

,使其產生的項目每次致電fn()。不足以做

max(countL(...)) 

再次。

+0

認爲這是我以後將不得不放棄一會兒,讓你知道。基本上,發生器甚至可以返回任何類,例如,然後在外部,您可以處理這種情況下特定的最大值。 –

+0

@J Spen正確。基本上,裝飾器將一個函數返回值轉換爲一個生成器,產生一個在walk中找到的每個文件的值。 – glglgl

+0

無論我嘗試什麼,我都無法像這樣正常工作。生成器只能調用next()一次。 –