我是新的python程序员,到目前为止我已经理解,“yield”关键字返回一个对象来代替生成器函数只返回生成器对象。
所以,如果我有一个包含10K项目的列表,我如何制作智能,pythonic解决方案,而不在列表中附加值并使其变大。
这意味着,我将一些值附加到列表中,最后创建一个大型列表,如下所示:
def example():
final_list = []
for i in range(0,10000):
final_list.append(i)
return final_list
这只是一个例子,不是真正的问题,我使用range()只是为了生成循环,在我的实际问题中,没有顺序数据,它将是随机字符串,而findla列表将包含10K串。 那么如何在不以有效的pythonic方式附加到列表的情况下获取所有值。
感谢。
答案 0 :(得分:5)
你的例子已经过度简化了,所以让我们假装你想要10000个随机数。
创建生成器有两种方法。一个是yield
语句:
def example():
for i in xrange(10000):
yield random.random()
另一种方法是使用generator expression:
(random.random() for i in xrange(10000))
您选择哪一个取决于您的代码复杂性。
答案 1 :(得分:2)
如果我理解你,那么你只使用range(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
如果您有一个返回字符串的函数,只需yield s
而不是构建列表。然后调用生成器函数并仅收集所需的值(此处不是字符串,但可以将整数除以100):
lst = [] # init
for x in gen(10000):
if x % 100 == 0:
lst.append(x)
print lst
循环也可以被所谓的列表理解所取代:
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
但是你可以在任何需要序列的地方使用生成器函数。如果您的生成器可以决定是否要收集您的元素,那么您可以简单地列出生成的元素,如下所示:
lst = list(gen(100))
print lst
答案 2 :(得分:2)
你说:
我在抓取网页并附加这些字符串后会收到一些字符串 字符串到列表,作为抓取大型数据的爬虫,列表正在获取 更大,最后当我想迭代列表,它的时间和内存 耗时
所以:
# 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 )
当您致电oneStringAtATime()
时,它会设置名为crawler()
的生成器功能;每次crawler()
执行yield
时,oneStringAtATime()
中的循环都会使用该字符串迭代一次。当crawler()
用完网页并退出该功能时,oneStringAtATime()
循环将退出。
答案 3 :(得分:0)
好的,通过阅读问题/查看OP代码和下面的一些评论,看起来OP正在使用列表。
所以,
def example():
final_list = range(0, 10000) # or xrange() for v 2.x
return final_list
也可能没有临时的final_list变量,但为了清楚起见。
如果列表的值不是range / xrange生成的系列,那么list comprehension就适用于此。
仍然觉得这个问题有点不清楚。
答案 4 :(得分:0)
>>> xrange_object = xrange(10000)
>>> xrange_object[0]
0
>>> xrange_object[1]
1
我看到你编辑了你的问题。如果您有一个随机字符串生成函数ran_string
,您可以使用生成器表达式来执行您想要的操作,如下所示:
>>> final_gen = (ran_string(i) for i in xrange(10000))
答案 5 :(得分:0)
你的问题不是很清楚 - 你在这里寻找的是generator expression。
E.g:
>>> values = (random.random() for _ in range(10))
>>> for value in values:
... print(value)
...
0.32161489939829857
0.285715480204797
0.4961165128957876
0.42658612656828354
0.5083396364418685
0.00843781669361321
0.49698036590463757
0.8067300769956716
0.5741614069287628
0.4728079544997392
如果您想迭代所拥有的值,可以使用生成器表达式根据现有的iterable生成值,而无需预先构建列表。它们是在请求时生成的(在这种情况下,当循环请求它们时)。
检查上面链接的视频,以便更深入地解释生成器表达式的语法(以及所有它的表兄弟,列表组合,设置组合等...)。
答案 6 :(得分:0)
你的问题有点不清楚,但我会假设你的意思是你想要一个可以迭代的对象,但是它是懒惰的 - 即不会预先计算并存储所有值。
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语句。
我希望有所帮助!