2012-11-07 2 views
3

8 줄의 코드를 단지 2 줄로 변환 할 수있었습니다.목록 이해 최적화

최초의 지능형리스트 나에게 폴더를 얻고, 두 번째는 나에게 특정 필터의 파일을 가져옵니다

hideTheseFolders=[".thumb",".mayaSwatches","RECYCLER","$AVG"] 
fileFilters=["ma","jpg","png","mb",'iff','tga','tif'] 
newLst=[] 
import os 
locationTxt="E:\box\scripts" 
[newLst.append(each) for each in os.listdir(locationTxt) if os.path.isdir(os.path.join(locationTxt,each)) and each not in hideTheseFolders] 
[newLst.append(os.path.basename(os.path.join(locationTxt,each))) for nfile in fileFilters for each in os.listdir(locationTxt) if each.endswith(nfile)] 

이제 위의 코드에서 마지막 두 줄이 locationTxt에서 같은 디렉토리 내에서 찾고, 거기에 의미 아마도 마지막 두 줄을 병합 할 수있는 방법 일 것입니다. 어떤 제안?

+4

왜 목록 이해력 내에서 목록에 추가하고 있습니까? – Marcin

+0

두 줄을 사용하는 것이 좋습니다. 이미 각기 다른 것들이 많이 있습니다 (어쨌든 표준 선 길이에 맞지도 않습니다). 그리고 각각 다른 것이 있습니다. 아마 당신은'newLst.extend()'를 각 comprehension의 결과로 할 수 있습니다. – DNA

+0

왜 이것을 두 줄로 병합 하시겠습니까? –

답변

2

.

특히, 목록 내재는 이 아니며 '최적화'기술은이 아닙니다. 파이썬 컴파일러가리스트 이해력을 보게되면, 그것을 for 루프로 나눕니다. 지능형리스트는 또한 타이밍에 의해 알 수있는 루프를위한 동일한것을

In [1]: from dis import dis 

In [2]: code = "[i for i in xrange(100)]" 

In [3]: dis(compile(code, '', 'single')) 
    1   0 BUILD_LIST    0 
       3 LOAD_NAME    0 (xrange) 
       6 LOAD_CONST    0 (100) 
       9 CALL_FUNCTION   1 
      12 GET_ITER    
     >> 13 FOR_ITER    12 (to 28) 
      16 STORE_NAME    1 (i) 
      19 LOAD_NAME    1 (i) 
      22 LIST_APPEND    2 
      25 JUMP_ABSOLUTE   13 
     >> 28 POP_TOP    
      29 LOAD_CONST    1 (None) 
      32 RETURN_VALUE  

사실 : 13 바이트 (FOR_ITER) 봐.A는 실제로 최소한의 성능 저하와 루프 (대개 작은 차이가로

In [4]: %timeit l = [i for i in xrange(100)] 
100000 loops, best of 3: 13.6 us per loop 

In [5]: %%timeit l = []; app = l.append # optimise out the attribute lookup for a fairer test 
    ...: for i in xrange(100): 
    ...:  app(i) 
    ...: 
100000 loops, best of 3: 11.9 us per loop # insignificant difference. Run it yourself and you might get it the other way around 

당신은 그러므로 주어진 지능형리스트를 작성할 수 있습니다 :이 경우에 대한 루프는 실제로 빠른 약간 (그러나 하찮게) 밖으로 일 속성 검색으로 인해), 종종 중요한 가독성 이점을 제공합니다. 특히 부작용이있는 루프는 이 아니고은 목록 포함으로 작성해야합니다. for 키워드가 두 개 이상 있거나 70자를 초과하는 줄을 만드는 목록 내포를 사용해서도 안됩니다. 이것들은 어렵고 빠른 규칙이 아니며, 읽을 수있는 코드를 작성하기위한 발견 적 방법입니다.

나를 잘못 이해하지 마라. 목록의 이해는 매우 유용하며, for-loop-and-append보다 더 명확하고 간단하며 간결해질 수 있습니다. 그러나 그들은이 방법으로 학대 당하지 않아야합니다.

1

주요 제안은 괜찮은 Python 책을 읽고 잘 읽는 것입니다. 코드에서 판단 해 보면 목록 이해력이 어떻게 작동하는지 알 수 없지만 8 개의 코드 행을 지나치게 길고 이해하기 어려운 코드 행에 넣을 수 있습니다.

당신은 읽기 쉬운 프로그램을 작성해야 :

  • 공간이 친구가
  • 라인이 화면에 (< 50 자)를 맞아야도 있습니다을 사용

    • 줄 바꿈이 당신의 친구를
    • 는 파이썬 책을 읽고 파일의 시작 부분에 imports을 넣어
    그냥 당신이 궁금해하는 경우 16,

    가, 여기에 코드가 같아야 작업은 다음과 같습니다

    import os 
    
    path = 'e:/box/scripts' 
    
    newLst = list() 
    for root,dirs,files in os.walk(path) : 
        # add folders 
        newLst.extend([dir for dir in dirs if dir not in hideTheseFolders]) 
    
        # add files 
        newLst.extend([file for file in files if file.lower().endswith(fileFilters)]) 
    
        break # don't descend into subfolders 
    
    # convert to the full path or whatever you need here 
    newLst = [os.path.join(path, file) for file in newLst] 
    
  • +0

    나를 믿어 라. 나는 벼락치기를하지 않았지만 어떻게 생각하고 싶은지를 생각해 낸다. –

    +0

    그런 다음 당신의 목적은 무엇입니까? – lenik

    +0

    여전히 답을 얻지는 못했지만 추천 된 내용을 받아 들였습니다. –

    4

    첫째, 당신이 그들 내부에 추가하여 루프를 숨길 수있는 지능형리스트를 남용하고; 당신은 실제로 목록 이해의 결과를 버리고 있습니다. 둘째, 가독성을 희생하면서 가능한 한 많은 내용을 한 줄로 채울 필요가 없습니다. 당신이 것 때문에,이 함축 여전히 있다는 것을

    ignore_dirs = set([".thumb",".mayaSwatches","RECYCLER","$AVG"]) 
    extensions = ["ma", "jpg", "png", "mb", 'iff', 'tga', 'tif'] 
    location = "E:\\box\\scripts" 
    
    filelist = [fname for fname in os.listdir(location) 
            if fname not in ignore_dirs 
            if os.path.isdir(os.path.join(location, fname))] 
    filelist += [os.path.basename(fname) 
          for fname in os.listdir(location) 
          if any(fname.endswith(ext) for ext in extensions)] 
    

    참고 : 루핑 및 필터링하여 목록을 작성 꽤 좋은 아이디어가 실제로 지능형리스트를 사용하려면

    ,이 버전을 고려 논리적으로 두 가지 종류의 항목으로 구성된 목록을 작성하는 것입니다. += 문 대신에 +이라는 두 개의 내포를 사용할 수도 있지만 단일 표현식으로 시도하고 수행 할 필요는 없습니다.

    는 (나는 그들이 무엇을 나타내는 반영하도록 변수의 이름을 변경의 자유를했다.) 당신은 한 줄의 코드가 어떻게 든 더 이상, 더 명시 적으로 (그리고 더 읽기) 코드보다 더 낫다고 생각하는 것

    0

    내가 읽을 수있는 코드를 사용하면 목록 이해가 어려워 지거나 목록 이해가 필요한 경우 읽을 수있는 백업 참조를 보관할 것입니다.

    지금까지 목록 작성을 배우면서 모든 사람이 따라갈 수 있도록 목록을 작성했습니다. 이해를위한

    주된 용도는 : files = [f for f in list_files() if f.endswth("mb")]

  • 반복 가능한 유형 간의 변환 : example = "abcde"; letters = [x for x in example] # this is handy for data packed into strings!
  • 단순리스트 처리

    • 영구리스트에 반복자 (아마도 필터)의 결과를 잡는 : strings = [str(x) for x in list_of_numbers]
    • 가독성을 위해 람다를 사용한 더 복잡한 목록 처리 : filter_func = lambda p, q: p > q larger_than_last = [val for val in list_of_numbers if filter_func(val, 5)]

    입력 해 주신 모든 분께 감사드립니다.

    업데이트 : 내 조사 및 문제 해결을 통해 정확한 답변을 얻을 수 있습니다.

    그러나 내가 읽을 수있는 코드 논리에 집착하는 것은가는 길입니다 !!!

  • +0

    당신은 그것을 파악한 것 같습니다! 'letters = [x를위한 x는 예제에서]'또한'letters = list (x)'로 표현할 수 있음에 유의하십시오. –

    +0

    또한 'lambda'를 사용한 예제는리스트 comprehension 안에 비교를 넣으면 더 잘 읽힌다 : '[val for list_of_numbers if val> 5]'. 필터 함수가 이것보다 복잡하다면, 아마도'def' 문을 사용하고'filter_func'보다 더 나은 이름을 주어야합니다. –