本问题已经有最佳答案,请猛点这里访问。

Python提供了一种很好的方法来获取渴望的可迭代len(x)的长度。 但是对于以生成器理解和函数表示的惰性可迭代对象,我找不到类似的东西。 当然,写这样的东西并不难:

1

2

3

4

5

6

7

8def iterlen(x):

n = 0

try:

while True:

next(x)

n += 1

except StopIteration: pass

return n

但是我无法摆脱正在重新装备自行车的感觉。

(虽然我正在键入该函数,但我的脑海中浮现了一个念头:也许确实没有这样的函数,因为它"破坏了"其参数。不过,对于我的情况而言,这不是问题)。

P.S .:关于第一个答案-是的,类似len(list(x))的东西也可以工作,但是会大大增加内存的使用。

P.P.S .:重新检查...忽略P.S.,似乎我在尝试时出错,它可以正常工作。 抱歉,添麻烦了。

建议仅将标题更改为发电机输出长度-可以扔掉重复的物品。 否则,这个问题就会与另一个混淆。

reimplementing a bicycle-几乎就像在重新发明轮子一样,只有程序员这样说。

最简单的方法可能只是sum(1 for _ in gen),其中gen是生成器。

尽管我喜欢此解决方案,但这里的主要缺点是,通过阅读您想要实现的代码,它一点都不明显。如果我在其他人的代码中看到这一行,我会停下来想一想"他为什么要在这里取这笔钱?" -除非之前没有看到这个" hack"。

@CharlesSalvia那是对恕我直言的评论。 Id说,获取生成器的长度值得评论。

另一个主要缺点是,它耗尽了发电机的功率只是为了达到长度,这通常首先破坏了发电机的整个目的。

请注意,这可能会减少内存消耗,但似乎比仅将其转换为列表要慢。

没有一个是因为您通常无法做到这一点-如果您有一个惰性无限生成器怎么办?例如:

1

2

3

4

5def fib():

a, b = 0, 1

while True:

a, b = b, a + b

yield a

这永远不会终止,但会生成斐波那契数。您可以通过调用next()获得任意数量的斐波纳契数。

如果您确实需要知道项目的数量,那么无论如何都无法一次线性地遍历它们,因此只能使用其他数据结构,例如常规列表。

我不确定我是否相信/接受这种解释。 sum采取可迭代方式,即使该可迭代方式可能是无限的,因此"在一般情况下您不能做到"比在一般情况下可以做到的要多。也许更可能的原因是人们"期望" len为O(1),这对于一般的可迭代项而言不是吗?

常规列表会占用更多内存,这是OP希望避免的事情。

@Steve Jessop:如果您有很多对象,则将它们计数通常显然是O(n)。如果在收集对象时跟踪对象的数量,则为O(1)。在许多特殊情况下,您可能可以使用对象的性质来构成更好的算法(即通过称量米数)。如果对象在内存中对齐,则可以使用内存消耗来计数对象。但是对于发电机,通常没有这种方法。

我有一个过滤后的列表,预计大约为2000000000个元素。我不能只使用常规列表;我需要使用发电机。现在,由于这些元素的来源方式,我实际上可以非常高效地运行它们-我无法存储它们,因为我没有40个内存。这个答案对我完全没有用。

1

2def count(iter):

return sum(1 for _ in iter)

或者更好:

1

2

3

4

5def count(iter):

try:

return len(iter)

except TypeError:

return sum(1 for _ in iter)

如果不是可迭代的,它将抛出一个TypeError。

或者,如果您想计算生成器中特定的内容:

1

2

3

4

5

6

7

8

9def count(iter, key=None):

if key:

if callable(key):

return sum(bool(key(x)) for x in iter)

return sum(x == key for x in iter)

try:

return len(iter)

except TypeError:

return sum(1 for _ in iter)

因此,对于那些想了解该讨论摘要的人。使用以下方法计算长度为5000万的生成器表达式的最终最高分:

len(list(gen))

len([_ for _ in gen]),

sum(1 for _ in gen),

ilen(gen)(来自more_itertool),

reduce(lambda c, i: c + 1, gen, 0),

按执行性能(包括内存消耗)排序,会让您感到惊讶:

```

1:test_list.py:8:0.492 KiB

1gen = (i for i in data*1000); t0 = monotonic(); len(list(gen))

("列表,秒",1.9684218849870376)

2:test_list_compr.py:8:0.867 KiB

1gen = (i for i in data*1000); t0 = monotonic(); len([i for i in gen])

('list_compr,sec',2.5885991149989422)

3:test_sum.py:8:0.859 KiB

1gen = (i for i in data*1000); t0 = monotonic(); sum(1 for i in gen); t1 = monotonic()

('sum,sec',3.441088170016883)

4:more_itertools / more.py:413:1.266 KiB

1

2

3

4d = deque(enumerate(iterable, 1), maxlen=1)

test_ilen.py:10: 0.875 KiB

gen = (i for i in data*1000); t0 = monotonic(); ilen(gen)

('ilen,sec',9.812256851990242)

5:test_reduce.py:8:0.859 KiB

1gen = (i for i in data*1000); t0 = monotonic(); reduce(lambda counter, i: counter + 1, gen, 0)

('reduce,sec',13.436614598002052)

```

因此,len(list(gen))是最频繁且消耗较少的内存

这是最好的答案

您可以使用enumerate()遍历生成的数据流,然后返回最后一个数字-项目数。

我尝试将itertools.count()与itertools.izip()一起使用,但没有运气。这是我提出的最好/最短的答案:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19#!/usr/bin/python

import itertools

def func():

for i in 'yummy beer':

yield i

def icount(ifunc):

size = -1 # for the case of an empty iterator

for size, _ in enumerate(ifunc()):

pass

return size + 1

print list(func())

print 'icount', icount(func)

# ['y', 'u', 'm', 'm', 'y', ' ', 'b', 'e', 'e', 'r']

# icount 10

Kamil Kisiel的解决方案更好:

1

2def count_iterable(i):

return sum(1 for e in i)

使用reduce(function,iterable [,initializer])获得内存有效的纯函数解决方案:

1

2

3>>> iter ="This string has 30 characters."

>>> reduce(lambda acc, e: acc + 1, iter, 0)

30

您的时间安排不对,因为迭代器正在被消耗。实际上,只有在len(list(iter))上的第一次尝试才对任何值进行迭代,所有其他值都在计数零长度序列。在我的测试中,reduce比len(list()),enumerate和sum慢。

@Blckknght谢谢,纠正了。

尝试使用more_itertools软件包以获得简单的解决方案。例:

1

2

3

4

5

6

7

8>>> import more_itertools

>>> it = iter("abcde") # sample generator

>>> it

>>> more_itertools.ilen(it)

5

有关另一个应用示例,请参见本文。

根据定义,只有一定数量的参数(具有预定义的长度)后,才会生成器的子集返回,即使这样,这些有限生成器中只有一个子集具有可预测的结局(访问生成器会产生副作用,即可以更早停止发电机)。

如果要为生成器实现length方法,则必须首先定义您认为的"长度"(是元素的总数还是剩余元素的数量?),然后将生成器包装在一个类中。这是一个例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25class MyFib(object):

"""

A class iterator that iterates through values of the

Fibonacci sequence, until, optionally, a maximum length is reached.

"""

def __init__(self, length):

self._length = length

self._i = 0

def __iter__(self):

a, b = 0, 1

while not self._length or self._i < self._length:

a, b = b, a + b

self._i += 1

yield a

def __len__(self):

"This method returns the total number of elements"

if self._length:

return self._length

else:

raise NotImplementedError("Infinite sequence has no length")

# or simply return None / 0 depending

# on implementation

使用方法如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42In [151]: mf = MyFib(20)

In [152]: len(mf)

Out[152]: 20

In [153]: l = [n for n in mf]

In [154]: len(l)

Out[154]: 20

In [155]: l

Out[155]:

[1,

1,

2,

...

6765]

In [156]: mf0 = MyFib(0)

In [157]: len(mf0)

---------------------------------------------------------------------------

NotImplementedError Traceback (most recent call last)

in ()

----> 1 len(mf0)

/tmp/ipython_edit_TWcV1I.py in __len__(self)

22 return self._length

23 else:

---> 24 raise NotImplementedError

25 # or simply return None / 0 depending

26 # on implementation

NotImplementedError:

In [158]: g = iter(mf0)

In [159]: l0 = [g.next(), g.next(), g.next()]

In [160]: l0

Out[160]: [1, 1, 2]

这是实现可以为len()函数提供长度的迭代器/生成器的解决方案。您可以通过实现自己的__iter__方法以及必要时自己的__init__和__len__方法来从此类派生生成器。这种模式可能很有用,例如对于某些ORM类型的对象,您可以在其中执行SQL查询,然后使用游标(通过迭代器)逐行获取结果,并且__len__方法从实际的SQL查询中获取计数。

这是一个技巧,但是如果您真的想让len在常规可迭代项上工作(以某种方式使用),则可以创建自己的len版本。

len函数在本质上等效于以下内容(尽管实现通常会提供一些优化以避免不必要的查找):

1

2def len(iterable):

return iterable.__len__()

因此,我们可以定义new_len进行尝试,如果__len__不存在,则可以通过消耗iterable来自己计算元素的数量:

1

2

3

4

5def new_len(iterable):

try:

return iterable.__len__()

except AttributeError:

return sum(1 for _ in iterable)

上面的代码在Python 2/3中有效,并且(据我所知)应该涵盖所有可能的迭代类型。

覆盖内置函数将掩盖原始行为,从而导致难以(或不可能)调试代码。您确实应该为该函数使用一个不同的名称,即不要命名为len ...

python怎么打印列表长度_关于python:生成器输出的长度相关推荐

  1. python 二维列表从小到大_给Python开发者准备的110道面试题

    信息量非常大!这是给Python开发者准备的110道笔试面试题,我只把问题列出来了,答案见文末,建议每道题都要认真刷一遍,有些题可以尝试用多种方式来解答,甚至做延伸学习,说真的,很多题都可以单独拎出来 ...

  2. python用户输入列表有缺陷_利用Python对Jira缺陷进行管理操作

    转自:51testing 1.1.概要 本文主要内容是教大家学习如何利用Python对Jira缺陷进行管理操作. 在平时的测试中,大家对于缺陷管理平台一定不陌生,平时的缺陷都要去平台进行操作.今天我们 ...

  3. python中对列表排序_在Python中对嵌套列表进行排序和分组

    在Python中对嵌套列表进行排序和分组 我具有以下数据结构(列表列表) [ ['4', '21', '1', '14', '2008-10-24 15:42:58'], ['3', '22', '4 ...

  4. python 批量打印文档_使用python将Excel数据填充Word模板并生成Word

    [项目需求] Excel中有一万多条学生学平险数据,需要给每位学生打印购买回执单,回执单包括学生姓名,身份证号,学校等信息,目前只能从Excel拷贝数据到Word模板中,然后打印,效率及其低下,寻求帮 ...

  5. python如何打印txt文件_在Python中的.txt文件中打印特定行?

    I have got a .txt file that contains a lot of lines. I would like my program to ask me what line I w ...

  6. python名片打印程序代码_基于Python的名片识别接口调用代码实例

    #!/usr/bin/python # -*- coding: utf-8 -*- import json, urllib from urllib import urlencode #-------- ...

  7. python二维列表排序_使用Python按顺时针方向排序二维坐标列表?

    这应该说明问题,给出一个可视化工具 但对于在同一距离上获得一组点的正确入口点来说,这并不总是有效的import random import pylab import cmath from iterto ...

  8. python如何打印井号_井字游戏(python)

    问题描述 设计一个算法,判断玩家是否赢了井字游戏.输入是一个 N x N 的数组棋盘,由字符" ","X"和"O"组成,其中字符" ...

  9. python如何打印乘法表_用python打印乘法表

    我决定用更复杂的策略来实践我的嵌套for循环逻辑,尽管有几种更简单的方法.我是一个初学者,所以我希望我的文档不会混淆我的思维过程.在 ^{1}$ 以下是我当前的输出: ^{pr2}$ 我尝试了一些快速 ...

  10. python输出列表元素_在Python中分别打印列表中的每一个元素方法

    在Python中分别打印列表中的每一个元素方法 更新时间:2018年11月07日 15:12:03 作者:wintersshi 今天小编就为大家分享一篇在Python中分别打印列表中的每一个元素方法, ...

最新文章

  1. (opencv)ORB匹配算法
  2. html php 混编 H1,在一个HTML中h1标签能出现几次?h1标签和标题标签的差别是什么?...
  3. 关于时钟、中断的理解
  4. Apache CXF 3.0:JAX-RS 2.0和Bean验证1.1最终一起
  5. MaxCompute 项目子账号做权限管理
  6. VHDL学习之TEXTIO在仿真中的应用
  7. 屏幕元素创建的基本语法
  8. 高可用Redis(八):Redis主从复制
  9. 面向对象(二) 继承/里氏替换
  10. 分段函数是不是一定初等函数_分段函数的微积分例题选讲
  11. 各路由协议防环机制汇总(一)
  12. 黑客帝国产业链调查:熊猫烧香作者一年赚千万
  13. java验证码提交错误时_验证码输入错误后自动刷新验证码
  14. 七战DTCC铸成ACE Director 去哪儿网周彦伟畅聊数据库的十八般武艺
  15. .equal(String)与Stirng.equal()的区别
  16. mysql保存微信昵称特殊字符
  17. 交换机,集线器,路由器这三者如何区分,各自的作用是什么?
  18. 深度学习需要的显卡配置
  19. ipconfig/all详解
  20. 使用Java实现简单的监控系统

热门文章

  1. 电子对抗中DRFM的基本原理
  2. ubuntu安装numpy,matplotlib等
  3. pyqt webview 执行js
  4. Linux + Nginx + Uwsgi + Django 搭建单服务器
  5. 适配器模式:我真的不难
  6. 01 C语言程序设计--01 C语言基础--第3章 基本数据类型01
  7. (七)日志采集工具sleuth--分布式链路跟踪(zipkin)
  8. 首席数据官成为企业转型中的重要角色之一
  9. strncmp函数——比较特定长度的字符串
  10. oracle数据库日期时间参数大全(一)