更多pythonic实现,用于不断循环列表

时间:2017-04-18 18:40:32

标签: python

我有一个我想用来访问API的令牌列表。我希望始终能够选择列表中的下一个标记以供使用,当到达列表的末尾时,重新开始。

我现在有了这个,但是我发现它非常混乱且不可读。

class tokenz:
    def __init__(self):
        self.tokens = ['a', 'b', 'c', 'd', 'e']
        self.num_tokens = len(tokens)
        self.last_token_used = 0

    def select_token(self):
        if self.last_token_used == 0:
            self.last_token_used += 1
            return self.tokens[0]
        elif self.last_token_used < (self.num_tokens - 1):
            self.last_token_used += 1
            return self.tokens[self.last_token_used - 1]
        elif self.last_token_used == (self.num_tokens -1):
            self.last_token_used = 0
            return self.tokens[self.num_tokens - 1]

关于使这更加pythonic的任何想法?

1 个答案:

答案 0 :(得分:3)

使用itertools.cycle()获取无限重复项目列表的生成器。

In [13]: tokens = ['a', 'b', 'c', 'd', 'e']

In [14]: import itertools

In [15]: infinite_tokens = itertools.cycle(tokens)

In [16]: [next(infinite_tokens) for _ in range(13)]
Out[16]: ['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c']    

如果您真的想让发布的代码更简单,请使用模运算。

self.last_token_used = (self.last_token_used + 1) % len(self.tokens)

此外,您可以在Python列表中使用否定索引,因此您的if语句是不必要的:

In [26]: for n in range(len(tokens)):
    ...:     print('{}: tokens[{}] = {}'.format(n, n-1, tokens[n-1]))
    ...:
0: tokens[-1] = e
1: tokens[0] = a
2: tokens[1] = b
3: tokens[2] = c
4: tokens[3] = d

然后您的代码变为:

class tokenz:
    def __init__(self):
        self.tokens = ['a', 'b', 'c', 'd', 'e']
        self.num_tokens = len(self.tokens)
        self.last_token_used = 0

    def select_token(self):
        self.last_token_used = (self.last_token_used + 1) % self.num_tokens
        return self.tokens[self.last_token_used - 1]