代码之家  ›  专栏  ›  技术社区  ›  mortysporty

python如何使用dunder方法使“for iteration”在“len”处停止

  •  0
  • mortysporty  · 技术社区  · 7 年前

    我有几个用于调用c代码的python类,使用 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 array是固定大小的,以简化对c的调用(这里使用可变大小的数组不是一个选项)。数组的“实际”长度由 n_values 变量。

    例如,如果 价值观 是一个由三个数字组成的数组,比如 1 , 2 3 , values=[1, 2, 3, 0, 0] n_values=3 .

    一切都好。问题是当我实施 __len__ __getitem__ .

    我想能写出这样的代码

    for value in my_class:
        #do something
    

    但是迭代器似乎没有“得到”这个 价值观 -数组只是 n_值 长。也就是说,它似乎没有用 MyCClass.__len__ 停止迭代。相反,它似乎在 价值观 .

    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 回复  |  直到 7 年前
        1
  •  3
  •   wim    7 年前

    对于旧式迭代器类型,唯一的方法是 IndexError :

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

    对于更干净的解决方案,考虑使用更现代的迭代协议,即返回 迭代器 实例来自 __iter__ 方法定义在 可迭代的 here .

    推荐文章