解释python生成器以获得一个长列表

解释python生成器以获得一个长列表,python,oop,data-structures,Python,Oop,Data Structures,我是新的python程序员,到目前为止我所了解的是,“yield”关键字返回一个对象,而不是生成器函数只返回生成器对象 所以,如果我有一个包含10K个项目的列表,我如何在不在列表中添加值的情况下创建智能的pythonic解决方案并使其变大 这意味着,我将向列表添加一些值,最后创建一个大列表,如下所示: def example(): final_list = [] for i in range(0,10000): final_list.append(i) r

我是新的python程序员,到目前为止我所了解的是,“yield”关键字返回一个对象,而不是生成器函数只返回生成器对象

所以,如果我有一个包含10K个项目的列表,我如何在不在列表中添加值的情况下创建智能的pythonic解决方案并使其变大

这意味着,我将向列表添加一些值,最后创建一个大列表,如下所示:

def example():
    final_list = []
    for i in range(0,10000):
        final_list.append(i)
    return final_list
这只是一个例子,不是一个真正的问题,我使用range()只是为了生成循环,其他什么都没有,在我真正的问题中,没有顺序数据,它将是随机字符串,findla列表将包含10K字符串。 那么,如何才能在不以有效的python方式追加到列表的情况下获取所有值呢


谢谢。

好的,通过阅读问题/查看OP代码和下面的一些评论,OP似乎正在处理列表

所以

可能也可以不使用临时final_list变量,但为了清楚起见,请留下

如果列表中的值不是由range/xrange生成的序列,则此处适用

还是觉得问题有点不清楚

>>> xrange_object = xrange(10000)
>>> xrange_object[0]
0
>>> xrange_object[1]
1
我看到你已经编辑了你的问题。如果您有一个随机字符串生成函数,
ran\u string
,则可以使用生成器表达式执行您想要的操作,如下所示:

>>> final_gen = (ran_string(i) for i in xrange(10000))
lst = list(gen(100))
print lst

你的问题不是很清楚-你在这里寻找的是一个答案

例如:

如果您想迭代已有的值,可以使用生成器表达式基于现有的iterable生成值,而无需预先构建列表。它们在被请求时生成(在本例中,当循环请求它们时)


查看上面链接的视频,了解生成器表达式语法的更深入解释(以及它的所有表亲、列表补码、设置补码等等)。

如果我理解得很好,那么您可以使用
范围(0,10000)
来模拟序列。无论何时在函数定义中使用
yield
,它都将成为生成器函数。当使用(调用)生成器函数时,它返回迭代器——您看不到它。请尝试以下
gen()

def gen(n):
    while n > 0:
        yield n
        n -= 1    # decrement the value
然后您通常在循环中使用它:

for x in gen(10000):
    print x,         # comma to suppress new line
如果您有一个返回字符串的函数,只需
生成s
,而不是构建列表。然后调用generator函数并仅收集所需的值(此处不是字符串,而是可被100整除的数字):

循环也可以被所谓的列表理解所取代:

lst = [ x for x in gen(10000) if x % 100 == 0 ]
print lst
…当您这样写时,哪个更容易理解(即类似于上面的循环):

lst = [ x 
        for x in gen(10000) 
            if x % 100 == 0 ]
print lst
但是,您可以在任何需要序列的地方使用生成器函数。如果生成器可以实现是否收集元素的决策,那么您可以简单地制作一个生成元素的列表,如下所示:

>>> final_gen = (ran_string(i) for i in xrange(10000))
lst = list(gen(100))
print lst

您的示例过于简化,所以让我们假设您想要10000个随机数

有两种方法可以创建生成器。一种是使用
yield
语句:

def example():
    for i in xrange(10000):
        yield random.random()
另一种方法是:


您选择哪一个取决于您的代码复杂度。

您的问题有点不清楚,但我假设您的意思是您想要一个可以迭代的对象,但它是惰性的,即不预先计算和存储所有值

def example():
    for i in xrange(10000):
        yield i

g = example()
print g.next() # prints '0'
print g.next() # prints '1'
for x in g:
    print x # prints '2', '3', ..., '10000'
我在示例中使用了xrange,因为使用range会有点违背目的,很明显,您可以在函数中放入您想要的任何内容。它的工作方式是g将记住它的内部状态(在本例中是i的值),并在每次调用g.next()或迭代g时一直运行到下一个yield语句

我希望这有帮助

你说:

在抓取网页并附加这些内容之后,我得到了一些字符串 字符串到列表,当爬虫获取大数据时,列表将 更大,最后当我想要迭代列表时,它的时间和内存 消耗

因此:


调用
oneStringAtATime()
时,它会设置名为
crawler()
的生成器函数;每次
crawler()
执行
yield
oneStringAtATime()
中的循环使用该字符串迭代一次。当
crawler()
用完网页并退出函数时,
oneStringAtATime()
循环退出。

这真的是毫无意义的-
(i代表i in x)
完全没有意义(在这种情况下它什么都不做,在任何情况下都可以用
iter(x)
替换)-范围仍然会在2.x中首先生成列表,在3.x中,这将毫无用处。@Lattyware我理解Re2.x的注释-但是你能在3.x上扩展吗?你是说仅仅使用范围(0,10000)本身就足够了吗?我同意,在这种情况下,
I for I
是无用的。。习惯的力量:-/在3.x.中,你想要一个生成器还是一个列表?我认为你应该编辑这个问题使它更清楚。此外,逗号后应加空格:)我认为这个问题不应该被否决。他写道,他是一个Python初学者,对于初学者来说,总是很难找到一个好问题。我对问题的回答是+1;)但我的+1也向Niklas B.提出了修改/改进问题的建议。把问题弄清楚也能让你以后更容易理解答案。@NiklasB。我认为问题在于人们对提问者(非常不清楚)问题的理解不同。(为了澄清,我没有投反对票。)这里的“随机”指的是匿名数据,这些数据实际上是从几个网站上刮下来的,添加到一个列表中。哪个列表非常大one@Lattyware当前位置我认为你误解了这个问题。在我看来,OP实际上想要一台发电机。抱歉,只是不清楚这将创建一个列表。“我想OP是想阻止这种情况发生的。”NiklasB。我认为这就是OP想要的——如果你一开始就忽略发电机的话题,读下半场,他似乎想“合作”
(random.random() for i in xrange(10000))
def example():
    for i in xrange(10000):
        yield i

g = example()
print g.next() # prints '0'
print g.next() # prints '1'
for x in g:
    print x # prints '2', '3', ..., '10000'
# generator function to crawl web pages
def crawler():
    while iStillHaveWebPagesToCrawl():
        someStrings = getSomeStringsFromAWebPage()
        for aString in someStrings:
            yield aString

def oneStringAtATime():
    for aString in crawler():
        doSomethingWith( aString )