python 如何使用 dunder 方法使 "for-iteration" 停在 "len"

python how to make "for-iteration" stop at "len" using dunder methods

我有几个 Python 类 用于调用 C 代码,使用 c-types。 return 结构类似于下面的示例。

import ctypes

class MyCClass(ctypes.Structure):
    _fields_ = [('n_values', ctypes.c_int),\
                ('values', ctypes.c_double * 5)]

    def __repr__(self):
        return """n_values : {0}, values : {1}""".format(self.n_values,\
                             self.values)

    def __len__(self):
        return self.n_values

    def __getitem__(self, key):
        return self.values[key]

values 数组是固定大小的,以简化对 C 的调用(此处不能使用可变大小的数组)。数组的 "actual" 长度由 n_values 变量控制。

例如,如果 values 是三个数字的数组,例如 123values=[1, 2, 3, 0, 0]n_values=3 .

这一切都很好。问题是当我实施 __len____getitem__.

我希望能够写出这样的代码

for value in my_class:
    #do something

但是迭代器似乎 "get" values 数组只有 n_values 长。 IE。它似乎没有使用 MyCClass.__len__ 来停止迭代。相反,它似乎遍历了 values.

的整个长度
my_class = MyCClass()

my_class.n_values = 3
sample_values = [1, 2, 3]
for i in range(3):
    my_class.values[i] = sample_values[i]

i = 0
for value in my_class:
    print(i)
    i += 1
0
1
2
3
4

我要

i = 0
for value in my_class:
    print(i)
    i += 1
0
1
2

我知道我可以编码

for i in range(my_class):
    # do something with my_class[i]

但这不是我想要的。

有人知道如何解决这个问题吗?

对于老式迭代器类型,唯一的方法是引发一个 IndexError:

def __getitem__(self, key):
    if key >= len(self):
        raise IndexError
    return self.values[key]

为了更简洁的解决方案,请考虑使用更现代的迭代协议,即从 iterable 上定义的 __iter__ 方法返回一个 iterator 实例。记录在案 here.