gpt4 book ai didi

python - 实现 __iter__ 和 __getitem__ 的容器的自定义包装器

转载 作者:太空宇宙 更新时间:2023-11-03 16:19:43 29 4
gpt4 key购买 nike

我正在尝试为容器编写一个自定义包装类。为了实现迭代器协议(protocol),我提供了__iter____next__,并访问我提供的__getitem__:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals, with_statement
from future_builtins import *
import numpy as np

class MyContainer(object):

def __init__(self, value):
self._position = 0
self.value = value

def __str__(self):
return str(self.value)

def __len__(self):
return len(self.value)

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

def __iter__(self):
return self

def next(self):
if (self._position >= len(self.value)):
raise StopIteration
else:
self._position += 1
return self.value[self._position - 1]

到目前为止,一切都按预期进行,例如。 G。当尝试这样的事情时:

if __name__ == '__main__':
a = MyContainer([1,2,3,4,5])
print(a)
iter(a) is iter(a)
for i in a:
print(i)
print(a[2])

但是我在尝试使用numpy.maximum时遇到了问题:

b= MyContainer([2,3,4,5,6])
np.maximum(a,b)

引发“ValueError:无法将大小为 5 的序列复制到维度为 0 的数组轴”。

当注释掉 __iter__ 方法时,我得到了一个具有正确结果的 NumPy 数组(同时不再符合迭代器协议(protocol)):

print(np.maximum(a,b)) # results in [2 3 4 5 6]

当注释掉__getitem__时,我得到了MyContainer的一个实例

print(np.maximum(a,b)) # results in [2 3 4 5 6]

但我失去了对个别项目的访问权限。

有没有办法同时实现所有三个目标(Iterator-Protocol、__getitem__numpy.maximum 工作)?我做的事情有什么根本错误吗?

要注意:实际的包装类具有更多功能,但这是我可以重现该行为的最小示例。

(Python 2.7.12、NumPy 1.11.1)

最佳答案

你的容器是它自己的迭代器,这极大地限制了它。您只能迭代每个容器一次,之后,就迭代协议(protocol)而言,它被视为“空”。

用您的代码尝试一下,看看:

c = MyContainer([1,2,3])
l1 = list(c) # the list constructor will call iter on its argument, then consume the iterator
l2 = list(c) # this one will be empty, since the container has no more items to iterate on

当您不提供 __iter__ 方法,但实现了 __len__ 方法和接受小整数索引的 __getitem__ 方法时,Python将使用 __getitem__ 进行迭代。这样的迭代可以进行多次,因为创建的迭代器对象彼此不同。

如果您在从类中取出 __iter__ 方法后尝试上述代码,则两个列表都将是 [1, 2, 3],如预期的那样。您还可以修复自己的 __iter__ 方法,以便它返回独立的迭代器。例如,您可以从内部序列返回一个迭代器:

def __iter__(self):
return iter(self.value)

或者,正如 Bakuriu 的评论中所建议的那样:

def __iter__(self):
return (self[i] for i in range(len(self))

如果您有 __getitem__ 方法但没有 __iter__ 方法,则后一个版本本质上是 Python 将为您提供的版本。

关于python - 实现 __iter__ 和 __getitem__ 的容器的自定义包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38599902/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com