我需要获取连续数字,而输入数字不变。

所以我得到了Give(5)-> 1,Give(5)-> 2,依此类推,但随后:再次给出Give(6)-> 1,开始计数。

到目前为止,我使用迭代器函数count()和一个功能Give(num)来解决该问题,如下所示:

def count(start=1):
    n=start
    while True:
        yield n
        n +=1
def give(num):
    global last
    global a
    if num==last:
        ret=a.next()
    else:
        a=count()
        ret=a.next()
    last=num
    return ret


它有效,但是很丑陋:我有两个全局变量,必须在调用Give(num)之前设置它们。我希望能够在不预先设置'a = count()'和'last = 999'变量的情况下调用Give(num)。我很肯定有更好的方法可以做到这一点...

编辑:为了获得令人难以置信的快速和多样化的响应,我在这里有很多东西需要学习。

最佳答案

显而易见,要做的是使give成为对象而不是函数。*通过定义__call__方法可以使任何对象成为可调用的。

在此过程中,您的代码可以简化很多,所以让我们开始吧。

class Giver(object):
    def __init__(self):
        self.last, self.a = object(), count()
    def __call__(self, num):
        if num != self.last:
            self.a = count(1)
        self.last = num
        return self.a.next()

give = Giver()


所以:

>>> give(5)
1
>>> give(5)
2
>>> give(6)
1
>>> give(5)
1


如果需要,您还可以创建多个单独的提供者,每个提供者都有自己的单独的当前状态。

如果您想用更多状态扩展它,则该状态将进入实例变量。例如,您可以将lasta替换为将先前看到的值映射到计数器的字典:

class Giver(object):
    def __init__(self):
        self.counters = defaultdict(count)
    def __call__(self, num):
        return next(self.counters[num])


现在:

>>> give(5)
1
>>> give(5)
2
>>> give(6)
1
>>> give(5)
3




*我在这里略过了一步。您始终可以通过将变量和使用它们的所有内容(可能只是一个函数)放在函数或其他作用域中来删除全局变量,因此它们最终会作为自由变量出现在函数的闭包中。但是就您而言,我认为这只会使您的代码看起来“丑陋”(在您认为丑陋的意义上也是如此)。但是请记住,对象和闭包在功能上实际上是等效的,但在外观上却有所不同,因此,当一个看上去很丑陋时,请尝试另一个。

10-08 01:37