2014-10-22 2 views
0

다음은 재미 있습니다. 실제로 another question에 대한 답변을 작성한 후 filter 또는 생성기를 사용하여 예기치 않은 결과를 발견했습니다.필터 또는 생성기로 예기치 않은 결과가 발생했습니다.

from os.path import dirname 
dirs = {dirname(path) for path in paths} 

그리고 지금은 발전기의 목록 (또는 심지어 발전기를 만들고 싶어 :

paths = ['/directoryb/baba.txt', '/directorya/nigel.txt', '/directoryb/ralph.txt', '/directorya/jim.txt' 

내가 경로 목록의 다른 디렉토리의 집합을 만들 : 나는 파일 경로의 목록을 가지고 생성자), 각 요소는 동일한 디렉토리에 paths의 요소를 포함합니다. 그래서 내가 할 :

dirs_iter = [(path for path in paths if path.startswith(dir)) for dir in dirs] 

내가 실행 한 후 놀라지 않았다 :

for dir_iter in dirs_iter: 
    for path in dir_iter: 
     print(path) 

그리고 얻기 다음 : 이것은 분명히 잘못된 것입니다

/directorya/nigel.txt 
/directorya/jim.txt 
/directorya/nigel.txt 
/directorya/jim.txt 

. 나는 다음과 같은 문장을 사용하는 경우 그리고 아직 : 나는 발전기 대신 filter 및/또는 map를 사용하는 경우

/directoryb/baba.txt 
/directoryb/ralph.txt 
/directorya/nigel.txt 
/directorya/jim.txt 

:

# now I'm generating the lists instead of using generators 
dirs_iter = [[path for path in paths if path.startswith(dir)] for dir in dirs] 

인쇄 루프는 예상 답을 보여줍니다

dirs_iter = map(lambda dir: filter(lambda path: path.startswith(dir), paths), dirs) 

잘못된 대답을 너무 많이받습니다편집 :map/filter 버전이 실제로 작동합니다.

여기 무슨 일 이니?

답변

2

이름이 dir 인 경우 생성자을 정의 할 때가 아니라 을 찾아 볼 때 클로저입니다. 그때까지 dirdirs에서 마지막 값에 바인딩 마지막 : 내 실행 /directoryb 오히려 /directorya보다 마지막

>>> from os.path import dirname >>> paths = ['/directoryb/baba.txt', '/directorya/nigel.txt', '/directoryb/ralph.txt', '/directorya/jim.txt'] >>> dirs = {dirname(path) for path in paths} >>> def echo(value): ... print('echoing:', value) ... return value ... >>> dirs_iter = [(path for path in paths if path.startswith(echo(dir))) for dir in dirs] >>> for dir_iter in dirs_iter: ... print('Iterating over the next dir_iter generator') ... for path in dir_iter: ... print(path) ... Iterating over the next dir_iter generator echoing: /directoryb /directoryb/baba.txt echoing: /directoryb echoing: /directoryb /directoryb/ralph.txt echoing: /directoryb Iterating over the next dir_iter generator echoing: /directoryb /directoryb/baba.txt echoing: /directoryb echoing: /directoryb /directoryb/ralph.txt echoing: /directoryb >>> list(dirs) ['/directorya', '/directoryb'] 

파이썬 (3) 임의의 해시 종자를 사용하기 때문에

,하지만 당신이 볼 수있는 경우에만 우리는 실제로 dir 값이 액세스되고 에코 된 dir_iter 생성기에 대해을 반복하고 그 시점에서이 값이 하나의 값으로 설정됩니다. list(dirs) 줄은 dirs 집합이 값을 산출하는 순서를 보여줍니다.

filter()이 아니며에는이 문제가 있음을 유의하십시오. map()filter() 콤보가 제대로 작동합니다.

>>> dirs_iter = map(lambda dir: filter(lambda path: path.startswith(dir), paths), dirs) 
>>> for dir_iter in dirs_iter: 
...  for path in dir_iter: 
...   print(path) 
... 
/directorya/nigel.txt 
/directorya/jim.txt 
/directoryb/baba.txt 
/directoryb/ralph.txt 
관련 문제