【问题标题】:An autoincrementing callable?一个自动递增的可调用对象?
【发布时间】:2012-02-08 02:39:11
【问题描述】:

我有一个方法,我需要在其中将一个不断增加的整数传递给另一个函数。

我可以这样做:

def foo(i):
    print i

def bar():

    class Incrementer(object):
        def __init__(self, start=0):
            self.i = start

        def __get__(self):
            j = self.i
            self.i += 1
            return j

    number = Incrementer()
    foo(number)
    foo(number)
    foo(number)

正确输出0 1 2 ... 但我觉得我忽略了一种更简单(或内置)的方法?

【问题讨论】:

  • 您确定您的代码有效吗? __get__() 方法仅在从新样式类中检索属性时调用,此处似乎不会发生这种情况。
  • 是的,它工作正常。你的意思是它应该只在我这样做时才有效:number = new Incrementer()?这是为什么呢?
  • I doubt your code prints 0 1 2。而且我不是在谈论number = new Incrementer()——您似乎在这里混淆了语言,Python 中没有new 运算符。我说的是descriptors的调用。

标签: python auto-increment counter


【解决方案1】:

试试itertools.count() -- 它完全符合您的需要:

>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2

【讨论】:

    【解决方案2】:

    一般来说,如果您需要在对函数的一次调用和下一次调用之间保留状态,您需要的是对象(您的解决方案)或生成器。在某些情况下,一种会比另一种更简单,但原则上您的操作方式并没有错误(尽管您似乎在实现方面存在一些问题)。

    Sven 的建议,itertools.count(),是一个生成器。它的实现是这样的:

    def count():
        i = 0
        while True:
            yield i
            i += 1
    

    现在,如果您希望它像函数一样可调用,而不必执行 next(c),您可以定义一个包装器来实现它:

     def count(c=itertools.count()):
         return next(c)
    

    或者不可避免的单行 lambda:

    count = lambda c=itertools.count(): next(c)
    

    然后count() 每次调用它都会返回下一个整数。

    当然,如果您希望能够创建任意数量的可调用函数,每个函数都有自己的计数器,您可以为此编写一个工厂:

    def counter():
        return lambda c=itertools.count(): next(c)
    

    那就是:

    c = counter()
    print c()   # 0
    print c()   # 1
    # etc
    

    在我看来,这仍然比一个对象简单,但也不简单。如果您的状态或逻辑更复杂,对象的封装可能会胜出。

    【讨论】:

    • 或者count = itertools.count().__next__,或count = itertools.count().next 用于 Python 2.6 及更低版本。
    • @F.J:第二个变体适用于所有 2.x 版本,包括 2.7。 __next__() 仅在 3.x 中可用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 2020-10-17
    • 2011-09-16
    • 2010-10-31
    • 1970-01-01
    相关资源
    最近更新 更多