Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 高效地创建生成器以按顺序输出数字列表_Python_Python 3.x - Fatal编程技术网

Python 高效地创建生成器以按顺序输出数字列表

Python 高效地创建生成器以按顺序输出数字列表,python,python-3.x,Python,Python 3.x,我想创建一个输出递增数字列表的生成器。 前 我可以用蛮力的方式来实现这一点(不完全正确,但在这个应用程序中并不重要,因为它有两个0): 侧面图 Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 56.083 56.083 part2_extended.py:1(<module

我想创建一个输出递增数字列表的生成器。 前

我可以用蛮力的方式来实现这一点(不完全正确,但在这个应用程序中并不重要,因为它有两个0):

侧面图

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   56.083   56.083 part2_extended.py:1(<module>)
100000000   14.221    0.000   14.221    0.000 part2_extended.py:1(isGrowing)
     1278    0.001    0.000    0.004    0.000 part2_extended.py:17(meetsAdjacentCriteria)
100000000   13.181    0.000   27.452    0.000 part2_extended.py:25(isValid)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:28(findAdjacents)
100000001    9.726    0.000   10.689    0.000 part2_extended.py:81(generateNumbersStupid)
    24310    0.031    0.000    0.046    0.000 part2_extended.py:9(inRange)
        1   17.942   17.942   56.083   56.083 part2_extended.py:92(calculateCount)
        1    0.000    0.000   56.083   56.083 part2_extended.py:99(main)
     6630    0.000    0.000    0.000    0.000 {len}
     9524    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
   194480    0.016    0.000    0.016    0.000 {pow}


   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   49.618   49.618 part2_extended.py:1(<module>)
 46191900    6.844    0.000    6.844    0.000 part2_extended.py:1(isGrowing)
     1278    0.001    0.000    0.004    0.000 part2_extended.py:17(meetsAdjacentCriteria)
 46191900    6.827    0.000   13.677    0.000 part2_extended.py:25(isValid)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:28(findAdjacents)
 46191901   18.352    0.000   26.127    0.000 part2_extended.py:43(generateNumbersArray2)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:9(inRange)
        1    9.814    9.814   49.618   49.618 part2_extended.py:92(calculateCount)
        1    0.000    0.000   49.618   49.618 part2_extended.py:99(main)
 46198530    1.865    0.000    1.865    0.000 {len}
     9524    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    10224    0.001    0.000    0.001    0.000 {pow}

但这要慢得多

def generateNumbersArrayInPlace(startNumber, endNumber):
        start = [int(x) for x in str(startNumber-1)]
        for num in range(startNumber, endNumber):
                lastIndex = len(start) - 1
                start[lastIndex] = start[lastIndex] + 1
                for digit in range(lastIndex, -1, -1):
                        if start[digit] > 9:
                                start[digit] = 0
                                if digit == 0:
                                        start.insert(0,1)
                                else:
                                        start[digit-1] = start[digit-1] + 1
                        else:
                                break
                yield start[:]
还尝试过清洁剂:

def generateNumbersArray(startNumber, endNumber):
        for num in range(startNumber, endNumber+1):
                yield [int(x) for x in str(num)]
它的速度也要慢得多

def generateNumbersArrayInPlace(startNumber, endNumber):
        start = [int(x) for x in str(startNumber-1)]
        for num in range(startNumber, endNumber):
                lastIndex = len(start) - 1
                start[lastIndex] = start[lastIndex] + 1
                for digit in range(lastIndex, -1, -1):
                        if start[digit] > 9:
                                start[digit] = 0
                                if digit == 0:
                                        start.insert(0,1)
                                else:
                                        start[digit-1] = start[digit-1] + 1
                        else:
                                break
                yield start[:]
如果我尝试将所有内容保持在适当的位置,而不生成新的阵列,它会大大加快速度,但仍然会显著降低速度

def generateNumbersArrayInPlace(startNumber, endNumber):
        start = [int(x) for x in str(startNumber-1)]
        for num in range(startNumber, endNumber):
                lastIndex = len(start) - 1
                start[lastIndex] = start[lastIndex] + 1
                for digit in range(lastIndex, -1, -1):
                        if start[digit] > 9:
                                start[digit] = 0
                                if digit == 0:
                                        start.insert(0,1)
                                else:
                                        start[digit-1] = start[digit-1] + 1
                        else:
                                break
                yield start[:]
侧面图

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   56.083   56.083 part2_extended.py:1(<module>)
100000000   14.221    0.000   14.221    0.000 part2_extended.py:1(isGrowing)
     1278    0.001    0.000    0.004    0.000 part2_extended.py:17(meetsAdjacentCriteria)
100000000   13.181    0.000   27.452    0.000 part2_extended.py:25(isValid)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:28(findAdjacents)
100000001    9.726    0.000   10.689    0.000 part2_extended.py:81(generateNumbersStupid)
    24310    0.031    0.000    0.046    0.000 part2_extended.py:9(inRange)
        1   17.942   17.942   56.083   56.083 part2_extended.py:92(calculateCount)
        1    0.000    0.000   56.083   56.083 part2_extended.py:99(main)
     6630    0.000    0.000    0.000    0.000 {len}
     9524    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
   194480    0.016    0.000    0.016    0.000 {pow}


   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   49.618   49.618 part2_extended.py:1(<module>)
 46191900    6.844    0.000    6.844    0.000 part2_extended.py:1(isGrowing)
     1278    0.001    0.000    0.004    0.000 part2_extended.py:17(meetsAdjacentCriteria)
 46191900    6.827    0.000   13.677    0.000 part2_extended.py:25(isValid)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:28(findAdjacents)
 46191901   18.352    0.000   26.127    0.000 part2_extended.py:43(generateNumbersArray2)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:9(inRange)
        1    9.814    9.814   49.618   49.618 part2_extended.py:92(calculateCount)
        1    0.000    0.000   49.618   49.618 part2_extended.py:99(main)
 46198530    1.865    0.000    1.865    0.000 {len}
     9524    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    10224    0.001    0.000    0.001    0.000 {pow}

简介:

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   90.430   90.430 part2_extended.py:1(<module>)
100000000   14.977    0.000   14.977    0.000 part2_extended.py:1(isGrowing)
        1    0.000    0.000   90.430   90.430 part2_extended.py:101(main)
     1278    0.001    0.000    0.004    0.000 part2_extended.py:17(meetsAdjacentCriteria)
100000000   14.289    0.000   29.317    0.000 part2_extended.py:25(isValid)
     1278    0.002    0.000    0.003    0.000 part2_extended.py:28(findAdjacents)
100000001   34.681    0.000   40.798    0.000 part2_extended.py:62(generateNumbersItertools)
    24310    0.032    0.000    0.048    0.000 part2_extended.py:9(inRange)
        1   20.315   20.315   90.430   90.430 part2_extended.py:94(calculateCount)
     6630    0.000    0.000    0.000    0.000 {len}
     9524    0.001    0.000    0.001    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
100000001    6.116    0.000    6.116    0.000 {next}
   194480    0.016    0.000    0.016    0.000 {pow}
ncalls tottime percall cumtime percall文件名:lineno(函数)
1 0.000 0.000 90.430 90.430部分2_扩展。py:1()
100000000 14.977 0.000 14.977 0.000第2部分扩展。py:1(正在增长)
1 0.000 0.000 90.430 90.430零件2_加长件:101(主)
1278 0.001 0.000 0.004 0.000零件2_扩展。py:17(满足相邻标准)
100000000 14.289 0.000 29.317 0.000第2部分扩展。py:25(有效)
1278 0.002 0.000 0.003 0.000零件2_扩展。py:28(FindAjacents)
100000001 34.681 0.000 40.798 0.000零件2_扩展。py:62(GenerateNumberSiteTools)
24310 0.032 0.000 0.048 0.000零件2_扩展。py:9(范围内)
1 20.315 20.315 90.430 90.430零件2_扩展py:94(计算计数)
6630 0.000 0.000 0.000 0.000{len}
9524 0.001 0.000 0.001 0.000{“列表”对象的“附加”方法}
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}
100000001 6.116 0.000 6.116 0.000{next}
194480 0.016 0.000 0.016 0.000{pow}

也非常慢。

我自己运行了一些测试,将您的“愚蠢”函数
generateNumberStudy()
与使用
itertools.product()
的函数进行比较,正如评论所说,它更快

对于以下每个函数,我都运行了10次试验,并计算了平均时间(请记住,我在执行期间遍历了函数返回的生成器中的所有元素):

愚蠢的功能

def generateNumbersStupid():
    for x1 in range(10):
            for x2 in range(10):
                    for x3 in range(10):
                            for x4 in range(10):
                                for x5 in range(10):
                                        for x6 in range(10):
                                            for x7 in range(10):
                                                for x8 in range(10):
                                                    yield [x1,x2,x3,x4,x5,x6,x7,x8]
平均时间:
16.513799535秒

itertools.product()生成器

def generateNumbersItertools():
    return product(range(10), repeat=8)
平均时间:
3.82409999371秒


它按照您最初的愿望清理代码,并且执行速度更快。在这种情况下,我看不到使用
生成器的必要性,特别是考虑到返回和遍历
列表
的速度要快得多。

我自己做了一些测试,将您的“愚蠢”函数
GenerateNumberStudy()
与使用
itertools.product()
的函数进行比较,正如评论所说,它更快

对于以下每个函数,我都运行了10次试验,并计算了平均时间(请记住,我在执行期间遍历了函数返回的生成器中的所有元素):

愚蠢的功能

def generateNumbersStupid():
    for x1 in range(10):
            for x2 in range(10):
                    for x3 in range(10):
                            for x4 in range(10):
                                for x5 in range(10):
                                        for x6 in range(10):
                                            for x7 in range(10):
                                                for x8 in range(10):
                                                    yield [x1,x2,x3,x4,x5,x6,x7,x8]
平均时间:
16.513799535秒

itertools.product()生成器

def generateNumbersItertools():
    return product(range(10), repeat=8)
平均时间:
3.82409999371秒


它按照您最初的愿望清理代码,并且执行速度更快。在这种情况下,看不到使用
生成器的必要性,特别是考虑到返回和遍历
列表的速度要快得多。

不运行配置文件,仅使用
timeit
我就看到了巨大的改进,通过使用
itertools.product
并将其与
itertools.dropwhile相结合,您的前导列表中不再有前面的零,尽管第一个输出将是一个空列表。这与您期望的输出最接近:

generateNumbers = (list(dropwhile((0).__eq__, p)) for p in product(range(10), repeat=8))
这导致:

[]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[1, 0]
[1, 1]
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[1, 6]
[1, 7]
...

没有运行配置文件,仅使用
timeit
我就看到了巨大的改进,通过使用
itertools.product
并将其与
itertools.dropwhile相结合,您的前导列表中不再有前面的零,尽管第一个输出将是一个空列表。这与您期望的输出最接近:

generateNumbers = (list(dropwhile((0).__eq__, p)) for p in product(range(10), repeat=8))
这导致:

[]
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[1, 0]
[1, 1]
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[1, 6]
[1, 7]
...

下面是一个递归生成器,它根据您的要求提供指定长度的序列:

def f(length):
    if length == 1:
        for i in range(1,10):
            yield [i]
    else:
        for ls in (x for x in f(length-1)):
            for i in range(10):
                yield ls + [i]
因此,您可以以任意长度调用它<代码>[x代表范围(1,3)内的i,x代表f(i)]
将导致:

[[1],
 [2],
 [3],
 [4],
 [5],
 [6],
 [7],
 [8],
 [9],
 [1, 0],
 [1, 1],
 [1, 2],
 [1, 3],
 [1, 4],
 ...
如果您正在寻找发电机:

for item in (x for i in range(1, some_number) for x in f(i)):
    #do stuff

下面是一个递归生成器,它根据您的要求提供指定长度的序列:

def f(length):
    if length == 1:
        for i in range(1,10):
            yield [i]
    else:
        for ls in (x for x in f(length-1)):
            for i in range(10):
                yield ls + [i]
因此,您可以以任意长度调用它<代码>[x代表范围(1,3)内的i,x代表f(i)]
将导致:

[[1],
 [2],
 [3],
 [4],
 [5],
 [6],
 [7],
 [8],
 [9],
 [1, 0],
 [1, 1],
 [1, 2],
 [1, 3],
 [1, 4],
 ...
如果您正在寻找发电机:

for item in (x for i in range(1, some_number) for x in f(i)):
    #do stuff

不确定是否有比上一种更快的方法,但为什么您首先需要这种方法?生成器不是免费的,如果您使用一个简单的
for
循环替换使用此生成器的代码,您可以获得更好的性能。创建此类内容的最简单方法是
从itertools导入组合与替换
@politinsa
组合与替换
生成固定长度随后。@Selcuk当我看到第二个版本的速度有多慢时,了解发生了什么就成了一个学术问题。但是把线圈从发电机里移开会快一点。很高兴听到。如果/当您需要可变性时,如何在调用方中强制转换列表?这肯定比while:True、嵌套迭代器和list comp hijinks快得多。在产品(范围(10,重复=8))中的x尝试
:列表(x)
。我敢打赌这是相当合理的。不确定是否有比上一个更快的方法,但为什么你首先需要这个?生成器不是免费的,如果您将使用此生成器的代码替换为简单的
for
循环,您可以获得更好的性能。创建此类内容的最简单方法是使用