Python for模循环 [英] Python for loop with modulo

查看:105
本文介绍了Python for模循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以通过模运算创建python for循环?我在Python中有一个环形缓冲区,我想迭代startPosendPos索引之间的元素,其中startPos的值可以比endPos大.在其他编程语言中,我将使用模运算符直观地实现这一点:

Is it possible to create a python for-loop with a modulo operation? I have a ringbuffer in Python and I want to iterate the elements between the startPos and endPos indexes, where startPos can have a bigger value than endPos. In other programming languages, I would intuitively implement this with a modulo operator:

int startPos = 6;
int endPos = 2;
int ringBufferSize = 8;
for(int i = startPos, i != endPos, i = (i+1) % ringBufferSize) {
    print buffer.getElementAt(i);
}

有没有一种方法可以在Python中轻松地做到这一点?我只找到了

Is there a way to do this easily in Python? I only found the

for i in list:
    print buffer[i]

语法,但是什么也不能解决我的问题.

Syntax but nothing which provides an equivalent solution to my problem.

我的下一个方法是在迭代存储在列表中的索引之前预先创建列表.但是,有没有办法像在其他编程语言中那样通过在for循环中直接使用模运算来像单行代码一样做到这一点呢?

My next approach would be to create the list in advance before iterate the indexes which are stored in the list. But is there a way to do this as a one-liner like in other programming languages by using the modulo operation directly in the for loop?

推荐答案

您有一些方法可以做到这一点:

You have some ways of doing that:

就像您在其他编程语言"(即C派生的语法)中所做的一样,只是您基本上必须在一段时间内编写其for循环-然后您才意识到C的for仍然是while :

As you do in "other programing languages" (i.e. C derived syntaxes), just that you basically have to write their for loop in a while form - and then you realize that C's for is just a while nonetheless:

start_pos = 6
end_pos = 2
ring_buffer_size = 8
i = start_pos
while True:
    i = (i + 1) % ring_buffer_size
    if i <= end_pos:
        break
    # your code here

现在,对于for语句,Python仅具有所谓的"for each"(始终),它总是遍历可迭代的或序列的.因此,您可以创建一个可迭代的变量,以产生您的值-

Now, for the for statement, Python only has what is called "for each" - which always walks an iterable or sequence. So you can create an iterable that will yield your values -

def ring(start, end, buffer_size, increment=1):
    i = start
    while i != end:
       yield i
       i += 1
       i %= buffer_size

for slot in ring(6, 2, 8):
    # your code here

请注意,尽管第二种形式更大",但它确实抽象了循环缓冲区逻辑,避免了硬代码值与它们的含义混合在一起,而无需查看它们-即,在for身体本身.

Note that while this second form is "bigger", it does abstract away your circular buffer logic, avoiding that hard code values get mixed with their meaning where you don't need to look at them - that is, inside the for body itself.

请注意,Python中for的实际想法是遍历 buffer 内容本身,而不是遍历将导致其内容的索引.
因此,Python标准库已经包含一个现成的循环缓冲区对象,该对象始终将其索引规范化为0和(len-1)- 只需从collections模块导入deque.

Note that the actual idea of for in Python is to iterate over the buffer contents itself, not and index that will lead to its contents.
So, the Python standard library includes a ready made circular buffer object already that always have its indexes normalized to 0 and (len - 1) - just import deque from the collections module.

如果您希望循环更改起始和结束索引的循环缓冲区taht可以在for语句中环绕并自动工作,这也相对容易-如果您不需要全部功能,只需子类list,添加startend索引,并对其__iter__方法进行自定义实现:

If you want a circular buffer with changing start and end indexes taht will wrap around and work automatically in forstatements, that is also relatively easy to do - if you don need the full functionality, just subclass list, add the start and end indexes, and make a custom implementation of its __iter__ method:

class Circular(list):

    def __init__(self, content, start, end):
        super(Circular, self).__init__( content)
        self.start = start
        self.end = end

    def __iter__(self):
        for i in range(self.start, self.start + len(self)):
            if i % len(self) == self.end: break
            yield self[i % len(self)]

现在您可以在代码中使用此自定义容器:

And now you can use this custom container in your code:

In [22]: mylist = Circular(range(8), 6 , 2)

In [23]: for i in mylist:
    ...:     print(i)
    ...:     
6
7
0
1

这篇关于Python for模循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆