>source

제목에 언급 된 패턴으로 튜플을 생성하는 가장 빠른 방법을 찾고 있습니다.

(1.0, 0.0, 0.0, 2.0, 0.0, 0.0, ..., N, 0.0, 0.0)

긍정의 어떤 긍정적 인 N에 대해 : round(N) == N .


  • 답변 # 1

    손을 can 수있는 가장 빠른 방법은 itertools 를 사용하는 것입니다.  모든 작업을 C 레이어로 푸시하는 함수 :

    from itertools import chain, repeat
    def make_tuple(N):
        return return tuple(chain.from_iterable(zip(map(float, range(1, round(N)+1)), repeat(0.0), repeat(0.0))))
    
    

    repeat  제로를 만든다, map(float, range(1, round(N)+1))  0이 아닌 값을 만듭니다. zip 그들을 함께 묶으면 3- tuple 어떤 chain.from_iterable  평평 해지다  최종 결과를 직접 생성합니다.

    일시적인 3- tuple 를 포함하지만 CPython 참조 인터프리터에서 s (Patrick의 답변과 달리) 실제로 새로운 tuple 를 만들지 않습니다. s;와이즈 비즈   tuple 를 재사용하도록 최적화되었습니다   zip 에 대한 다른 참조가없는 경우 새 결과의 마지막 결과에서  다음 값이 요청 될 때 존재하며 tuple  매번 참조를 공개합니다).

    다른 답변들과 비교하기 위해, tuple   chain.from_iterable 의 마이크로 벤치 마크  150 개 중 :

    ipython
    
    

    listcomps 및 genexprs를 사용하여 위의 접근 방식과 유사한 몇 가지 다른 접근 방식을 시도했지만 그 중 40 µs 미만이 아니므로 게시하지 않아도됩니다.

    Tim Peter의 솔루션은 지금까지 가장 빠른 게시이며 더 나아질 것 같지 않습니다. 그가 지적했듯이, 메모리 사용량이 많을 때 전체 결과를 저장하기 위해 스토리지가 필요하기 때문에 약간 더 많은 메모리가 필요합니다.  그리고 일시적인 N  (각각의 크기는 초과 할당없이 정확하게 조정되어야하지만) 컨테이너의 최대 메모리는 "필요한"것의 약 두 배입니다. 광산에는 >>> %timeit -r5 make_tuple(150) 28.1 µs ± 1.67 µs per loop (mean ± std. dev. of 5 runs, 10000 loops each) >>> %timeit -r5 make_tuple_tim_peters(150) 17.1 µs ± 52 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each) >>> %timeit -r5 make_tuple_julien(150) 154 µs ± 1.85 µs per loop (mean ± std. dev. of 5 runs, 10000 loops each) >>> %timeit -r5 tuple(values_patrick_haugh(150)) # Modified to convert to float properly 40.7 µs ± 1.29 µs per loop (mean ± std. dev. of 5 runs, 10000 loops each) 가 필요합니다  현재 CPython에서 구현 세부 사항으로 약 25 %의 초과 할당을 의미하는 결과가 얼마나 큰지 알지 못하기 때문에 전반적인 결과를 알 수 있습니다. 저축이지만 중요한 것은 아닙니다. 성능이 중요하다면 거의 항상 Tim의 솔루션을 사용합니다.

    나중에 업데이트 : 결국 Tim의 답을 능가하는 것을 찾을 수 있었지만 tuple 에 의지해야만 , 점진적 개선은 매우 사소합니다 :

    list
    
    

    팀의 대답과 기본적으로 동일합니다. 단지 tuple 를 사용합니다.  원시 C 기본 유형으로 일괄 작업을 수행합니다 (예 : numpy ).  파이썬 from numpy import arange, zeros def make_tuple_numpy(N): ret = zeros(3*round(N)) ret[::3] = arange(1., N+1.) return tuple(ret.tolist()) 를 만들지 않고 부동 소수점 형태로 직접 범위를 생성합니다. 오직 numpy 로 변환 s)는 np.arange 를 사용합니다.   int 하는 방법   float 로 변환을 수행  파이썬 반복자가 관여하지 않으면 tolist 에서 랩  생성자 (특별한 경우 numpy 따라서 반복자가 관여하지 않습니다). 그럼에도 불구하고 장점은 아주 사소합니다 :

    list
    
    

    팀의 솔루션에 비해 ~ 20 %의 런타임이 추가로 단축되지만,lot을 수행하지 않으면 tuple 가져 오기 비용  아마도 절약 효과를 없앨 수 있습니다.

  • 답변 # 2

    누가 아는가? ;-) CPython에서 "트릭"은 일반적으로 명시적인 파이썬 레벨 루프를 피하고 2 차 시간 카테 네이션을 피합니다. 한 가지 방법이 있습니다 :

    list
    
    

    예를 들어

    >>> %timeit -r5 make_tuple_numpy(150)
    13.8 µs ± 158 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)
    
    

    모든 실제 작업은 "C 속도로"실행되며 심지어 numpy  호출 def gentup(N): NI = round(N) assert N == NI result = [0.] * (3 * NI) result[::3] = map(float, range(1, NI + 1)) return tuple(result) 에도 불구하고 한 번만 조회됩니다  

  • 답변 # 3

    임시 튜플을 생성하지 않는 방법이 있습니다.

    >>> gentup(4)
    (1.0, 0.0, 0.0, 2.0, 0.0, 0.0, 3.0, 0.0, 0.0, 4.0, 0.0, 0.0)
    
    
    float

관련 자료

  • 이전 python - API에서 사전으로 데이터를 저장하는 방법
  • 다음 owl 온톨로지 - 보완 클래스 정의를 작성하는 방법?