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

时间:2018-05-30 06:32:56

标签: python magic-methods

我有几个用于调用C代码的Python类,使用c-types。返回结构看起来像下面的例子。

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(这里使用可变大小的数组不是一个选项)。 "实际"数组的长度由n_values变量控制。

例如,如果values是包含三个数字的数组,请说123values=[1, 2, 3, 0, 0]n_values=3。< / p>

这一切都很好。问题在于我实施__len____getitem__

我希望能够编写像这样的代码

for value in my_class:
    #do something

但迭代器似乎没有&#34;得到&#34; values - 数组的长度仅为n_values。即似乎没有使用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]

但这不是我想要的。

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

1 个答案:

答案 0 :(得分:3)

使用旧式迭代器类型,唯一的方法是引发IndexError

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

要获得更清晰的解决方案,请考虑使用更现代的迭代协议,即从 iterable 上定义的__iter__方法返回迭代器实例。记录here