2014-12-02 86 views
0

我想要使用一個上下文管理器來控制訪問子目錄,它似乎將它與一個生成器表達式結合起來會非常優雅,但它似乎不起作用。有什麼方法可以糾正這個問題嗎?我可以一起使用這兩種方法嗎?Python上下文管理器可以與生成器一起使用嗎?

這裏的例子:

import os, sys 
from contextlib import contextmanager 
from glob import glob 

@contextmanager 
def visitDir(d): 
    os.chdir(d) 
    yield d 
    os.chdir("..") 

paths = [os.path.join('.', p[0:-1]) for p in glob('*/')] 

def clean(): 
    for p in (visitDir(p) for p in paths): # This is the magic line 
     print p 
     print os.getcwd() 

clean() # Context manager apparently expires within the generator expression 
+0

我用*發生器表達式替換*流* *; *流*不是一個適用於此的概念。 – 2014-12-02 19:12:08

+0

雖然生成器表達式不會創建流​​,但評估只會在每次獲取新對象時發生,而不是像列表表達式一樣在前面進行評估? – user1677663 2014-12-02 19:47:54

+0

Python將一般概念稱爲迭代器。提示時,迭代器一次產生一個值。生成器表達式是用於以緊湊方式生成生成器的語法,其中生成器是一種專門的迭代器。你*可以*調用結果流,但這不是Python在這個概念的任何地方使用的術語。 – 2014-12-02 20:06:05

回答

2

你需要控制進入和離開上下文。生成器表達式沒有更廣泛的上下文概念,因此您不能只將上下文管理器放在生成器表達式中,並期望在生成時自動輸入上下文管理器。

只有with語句管理實際上下文,觸發CM上的__enter____exit__掛鉤。你可以使用所產生的上下文管理對象從這裏生成的表達:

def clean(): 
    for cm in (visitDir(p) for p in paths): 
     with cm as p: 
      print p 
      print os.getcwd() 

with語句調用cm.__enter__這裏,塊完成時cm.__exit__被調用。

但是我發現下面的更具可讀性和可理解:

def clean(): 
    for p in paths: 
     with visitDir(p): 
      print p 
      print os.getcwd() 

因爲在創建上下文管理作爲with線的一部分,只是更容易跟蹤。

+0

我同意,你的最終版本更具可讀性。如果我不必說'用釐米作爲p',那麼我的價值只會是值得的,而多餘的線條簡潔/優雅卻失去了。 – user1677663 2014-12-02 19:46:11

相關問題