programing

반복기에서 요소 목록을 만들려면 어떻게 해야 합니까(반복기를 목록으로 변환)?

telecom 2023. 6. 4. 10:17
반응형

반복기에서 요소 목록을 만들려면 어떻게 해야 합니까(반복기를 목록으로 변환)?

반복기가 지정user_iterator생성된 객체의 목록을 반복기에 어떻게 반복할 수 있습니까?

다음 코드가 있습니다. 작동하는 것 같습니다.

user_list = [user for user in user_iterator]

하지만 더 빠르고, 더 좋고, 더 정확한 것이 있을까요?

list(your_iterator)

파이썬 3.5부터 사용할 수 있습니다.*반복 가능한 포장 풀기 작업자:

user_list = [*your_iterator]

하지만 그것을 하는 비단결적인 방법은 다음과 같습니다.

user_list  = list(your_iterator)

@Robino는 타당한 테스트를 추가할 것을 제안했습니다. 따라서 다음은 반복기를 목록으로 변환하는 세 가지 가능한 방법(아마도 가장 많이 사용되는 방법) 사이의 간단한 벤치마크입니다.

  1. 형식 생성자별

    list(my_iterator)

  2. 짐을 풀어서

    [*my_iterator]

  3. 목록 이해력을 사용하여

    [e for e in my_iterator]

simple_bechmark 라이브러리를 사용해 왔습니다.

from simple_benchmark import BenchmarkBuilder
from heapq import nsmallest

b = BenchmarkBuilder()

@b.add_function()
def convert_by_type_constructor(size):
    list(iter(range(size)))

@b.add_function()
def convert_by_list_comprehension(size):
    [e for e in iter(range(size))]

@b.add_function()
def convert_by_unpacking(size):
    [*iter(range(size))]


@b.add_arguments('Convert an iterator to a list')
def argument_provider():
    for exp in range(2, 22):
        size = 2**exp
        yield size, size

r = b.run()
r.plot()

여기에 이미지 설명 입력

보시다시피, 생성자에 의한 변환과 언팩에 의한 변환 사이에는 차이를 만들기가 매우 어렵습니다. 목록 이해에 의한 변환은 "가장 느린" 접근 방식입니다.


다음과 같은 간단한 스크립트를 사용하여 여러 Python 버전(3.6, 3.7, 3.8, 3.9)에서도 테스트를 수행했습니다.

import argparse
import timeit

parser = argparse.ArgumentParser(
    description='Test convert iterator to list')
parser.add_argument(
    '--size', help='The number of elements from iterator')

args = parser.parse_args()

size = int(args.size)
repeat_number = 10000

# do not wait too much if the size is too big
if size > 10000:
    repeat_number = 100


def test_convert_by_type_constructor():
    list(iter(range(size)))


def test_convert_by_list_comprehension():
    [e for e in iter(range(size))]


def test_convert_by_unpacking():
    [*iter(range(size))]


def get_avg_time_in_ms(func):
    avg_time = timeit.timeit(func, number=repeat_number) * 1000 / repeat_number
    return round(avg_time, 6)


funcs = [test_convert_by_type_constructor,
         test_convert_by_unpacking, test_convert_by_list_comprehension]

print(*map(get_avg_time_in_ms, funcs))

스크립트는 주피터 노트북(또는 스크립트)의 하위 프로세스를 통해 실행되고, 크기 매개 변수는 명령줄 인수를 통해 전달되며 스크립트 결과는 표준 출력에서 가져옵니다.

from subprocess import PIPE, run

import pandas

simple_data = {'constructor': [], 'unpacking': [], 'comprehension': [],
        'size': [], 'python version': []}


size_test = 100, 1000, 10_000, 100_000, 1_000_000
for version in ['3.6', '3.7', '3.8', '3.9']:
    print('test for python', version)
    for size in size_test:
        command = [f'python{version}', 'perf_test_convert_iterator.py', f'--size={size}']
        result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
        constructor, unpacking,  comprehension = result.stdout.split()
        
        simple_data['constructor'].append(float(constructor))
        simple_data['unpacking'].append(float(unpacking))
        simple_data['comprehension'].append(float(comprehension))
        simple_data['python version'].append(version)
        simple_data['size'].append(size)

df_ = pandas.DataFrame(simple_data)
df_

여기에 이미지 설명 입력

당신은 여기서 제 노트 전체를 가져올 수 있습니다.

대부분의 경우, 제 테스트에서는 포장을 푸는 것이 더 빠르다는 것을 보여주지만, 그 차이가 너무 작기 때문에 결과가 실행에서 실행으로 바뀔 수 있습니다.다시 말하지만, 이해 접근법이 가장 느립니다. 사실 다른 두 가지 방법은 최대 60% 더 빠릅니다.

언급URL : https://stackoverflow.com/questions/3790848/how-can-i-create-a-list-of-elements-from-an-iterator-convert-the-iterator-to-a

반응형