Python itertools 计数器的当前值是多少
What is the current value of a Python itertools counter
Python (2.7.9) 中的 itertools.count
计数器对于线程安全计数非常方便。我怎样才能得到计数器的当前值?
每次您调用 next()
:
时,计数器都会递增 returns 最后一个值
import itertools
x = itertools.count()
print x.next() # 0
print x.next() # 1
print x.next() # 2
到目前为止,还不错。
我找不到不调用 next()
来获取计数器当前值的方法,调用 next()
会产生增加计数器或使用 repr()
函数的不良副作用.
接上文:
print repr(x) # "count(3)"
所以你可以解析 repr()
的输出。像
current_value = int(repr(x)[6:-1])
可以解决问题,但真的很难看。
有没有更直接获取计数器当前值的方法?
根据 documentation,无法访问函数的当前值。 itertools.count()
是来自 itertools
模块的 generator 方法。因此,通常的做法是简单地 将生成器的当前值赋值 给一个变量。
简单存储下一次调用的结果:
current_value = x.next()
或(Python版本≥2.6的内置python方法)
current_value = next(x)
如果您想要添加一些语法糖,您可以制作一个包装函数或实用装饰器 class,但赋值是标准的。
It是个生成器,想怎么弄都不容易
如果您想在多个地方使用它的值,我建议您通过 .next()
获取一个值并将其存储在一个变量中。如果您担心计数器可能会在这两次使用之间递增,您需要将它们都放在 critical section 中。
如果您不想用这些检查生成的额外“+1”污染该计数器,您可以再使用一个计数器来对检查进行计数(也将其放在关键部分)。从前者中减去后者会得到你所需要的。
还有,你真的确定线程安全吗?文档页面没有关于线程的内容。
使用来源,卢克!
根据module implementation,这是不可能的。
typedef struct {
PyObject_HEAD
Py_ssize_t cnt;
PyObject *long_cnt;
PyObject *long_step;
} countobject;
当前状态存储在 cnt
和 long_cnt
成员中,它们都没有暴露在对象 API 中。正如您所建议的,唯一可以检索它的地方是对象 __repr__
。
请注意,在解析字符串时,您必须考虑非奇异增量情况。 repr(itertools.count(123, 4))
等于 'count(123, 4)'
- 您所建议的逻辑在这种情况下会失败。
运行 今天也是一样。这是我最终得到的结果:
class alt_count:
def __init__(self, start=0, step=1):
self.current = start - step
self.step = step
def __next__(self):
self.current = self.current + self.step
return self.current
应该给你几乎所有的 itertools.count
功能加上 current
属性.
i = alt_count()
print(next(i)) # 0
print(next(i)) # 1
print(i.current) # 1
如果不需要当前值,我发现使用这个简单的 closure
also works. Note that nonlocal
仅适用于 Python 版本 > 3。
def alt_next_maker(start=0, step=1):
res = start - step
def alt_next():
nonlocal res, step
res = res + step
return res
return alt_next
如果您不想使用 itertools
模块,可以用作简单的替代方法。
alt_next = alt_next_maker()
print(alt_next()) # 0
print(alt_next()) # 1
文档还提到了以下等效内容:
def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
yield n
n += step
另一种在不推进迭代器的情况下获取下一个值的技巧是滥用复制协议:
>>> c = itertools.count()
>>> c.__reduce__()[1][0]
0
>>> next(c)
0
>>> c.__reduce__()[1][0]
1
或者直接从对象副本中获取:
>>> from copy import copy
>>> next(copy(c))
1
Python (2.7.9) 中的 itertools.count
计数器对于线程安全计数非常方便。我怎样才能得到计数器的当前值?
每次您调用 next()
:
import itertools
x = itertools.count()
print x.next() # 0
print x.next() # 1
print x.next() # 2
到目前为止,还不错。
我找不到不调用 next()
来获取计数器当前值的方法,调用 next()
会产生增加计数器或使用 repr()
函数的不良副作用.
接上文:
print repr(x) # "count(3)"
所以你可以解析 repr()
的输出。像
current_value = int(repr(x)[6:-1])
可以解决问题,但真的很难看。
有没有更直接获取计数器当前值的方法?
根据 documentation,无法访问函数的当前值。 itertools.count()
是来自 itertools
模块的 generator 方法。因此,通常的做法是简单地 将生成器的当前值赋值 给一个变量。
简单存储下一次调用的结果:
current_value = x.next()
或(Python版本≥2.6的内置python方法)
current_value = next(x)
如果您想要添加一些语法糖,您可以制作一个包装函数或实用装饰器 class,但赋值是标准的。
It是个生成器,想怎么弄都不容易
如果您想在多个地方使用它的值,我建议您通过 .next()
获取一个值并将其存储在一个变量中。如果您担心计数器可能会在这两次使用之间递增,您需要将它们都放在 critical section 中。
如果您不想用这些检查生成的额外“+1”污染该计数器,您可以再使用一个计数器来对检查进行计数(也将其放在关键部分)。从前者中减去后者会得到你所需要的。
还有,你真的确定线程安全吗?文档页面没有关于线程的内容。
使用来源,卢克!
根据module implementation,这是不可能的。
typedef struct {
PyObject_HEAD
Py_ssize_t cnt;
PyObject *long_cnt;
PyObject *long_step;
} countobject;
当前状态存储在 cnt
和 long_cnt
成员中,它们都没有暴露在对象 API 中。正如您所建议的,唯一可以检索它的地方是对象 __repr__
。
请注意,在解析字符串时,您必须考虑非奇异增量情况。 repr(itertools.count(123, 4))
等于 'count(123, 4)'
- 您所建议的逻辑在这种情况下会失败。
运行 今天也是一样。这是我最终得到的结果:
class alt_count:
def __init__(self, start=0, step=1):
self.current = start - step
self.step = step
def __next__(self):
self.current = self.current + self.step
return self.current
应该给你几乎所有的 itertools.count
功能加上 current
属性.
i = alt_count()
print(next(i)) # 0
print(next(i)) # 1
print(i.current) # 1
如果不需要当前值,我发现使用这个简单的 closure
also works. Note that nonlocal
仅适用于 Python 版本 > 3。
def alt_next_maker(start=0, step=1):
res = start - step
def alt_next():
nonlocal res, step
res = res + step
return res
return alt_next
如果您不想使用 itertools
模块,可以用作简单的替代方法。
alt_next = alt_next_maker()
print(alt_next()) # 0
print(alt_next()) # 1
文档还提到了以下等效内容:
def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
yield n
n += step
另一种在不推进迭代器的情况下获取下一个值的技巧是滥用复制协议:
>>> c = itertools.count()
>>> c.__reduce__()[1][0]
0
>>> next(c)
0
>>> c.__reduce__()[1][0]
1
或者直接从对象副本中获取:
>>> from copy import copy
>>> next(copy(c))
1