是否为迭代器写入权限?或者:向numpy Arrays的生成器发送值

时间:2012-03-29 08:20:24

标签: python numpy pass-by-reference generator yield

我是Python的迭代器的新手,所以也许我的语言并不总是正确的。

我有一个包含numpy.ndarray列表的类:

class wrapper:
    def __init__(self, myList):
        self.myList = myList

    def getArrayIterator(self):
        for arr in self.myList:
            yield arr

#set list of arrays in wrapper
myList = [rand(3,3), rand(3,3), rand(3,3)]
w = wrapper(myList)

据我了解,第二种方法返回一个生成器。 现在我想使用该生成器遍历列表并将数组重置为其他内容:

for a in w.getArrayIterator():
    a = zeros((3,4))

我希望在这里通过引用语义传递,但似乎并非如此。

所以我尝试在我的send()函数中使用Python的getArrayIterator

# ...
def getArrayIterator(self):
    for arr in self.myList:
        val = (yield arr)
        if val is not None:
            arr = val
# ...

但这不会起作用,因为:

a.send(zeros((3,4)))
  AttributeError: 'numpy.ndarray' object has no attribute 'send'

是否有一个简单的解决方案来实现我想要的行为? 我错过了什么吗?


编辑:有人向我指出,我应该提供有关我实际问题的更多信息。上面的例子当然是简化的。

我有一个numpy.ndarray列表,列出了我班级中封装的张量T.当访问T:t_ijkl的元素时,我需要将列表中存储的矩阵相乘:A(i)*B(j)*C(k)*D(l),第一个和最后一个是行/ col向量。

所以有一组A,一组B等等。每个都属于我的应用程序中的网格点。

我现在希望在与每个网格点关联的矩阵上的所有网格点和迭代器上都有一个迭代器。

首先想到的是使用迭代器c ++样式来读取和写入矩阵。但正如agf在下面指出的那样,这不是一个真正可行的方法。所以我想我会使用不同的迭代器来进行读取访问,使用专门的setter方法为矩阵设置新的值。

3 个答案:

答案 0 :(得分:2)

我假设这是一个简化的例子,因为你所拥有的类似乎没有理由不使用普通列表。

当你这样做时

name = somelist[0]
name = 'other'

您将名称name指向somelist中第一个索引处的对象,然后将名称name指向对象'other'。您永远不会将somelist[0]指向'other'

因此,除了send之外,您还需要实际分配到列表:

class wrapper:
    def __init__(self, myList):
        self.myList = myList

    def getArrayIterator(self):
        for i, arr in enumerate(self.myList):
            yarr = (yield arr)
            if yarr is not None:
                self.myList[i] = yarr

#set list of arrays in wrapper
myList = [1, 2, 3, 4, 5]
w = wrapper(myList)
witer = w.getArrayIterator()
try:
    a = next(witer)
    for i in range(6, 11):
        print a,
        a = witer.send(i)
except StopIteration:
    pass
print
print w.myList

答案 1 :(得分:0)

听起来好像你想要实施__getitem____setitem__

class wrapper:
    def __init__(self, myList):
        self.myList = myList    

    def __iter__(self):
        for arr in self.myList:
            yield arr    

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

    def __setitem__(self, key, value):
        self.myList[key] = value

用法:

for index, arr in enumerate(w):
    same_arr = w[index]
    w[index] = zeros((3,4))

如果您认为它会让您的生活更轻松,那么您可以实施许多其他有用的功能。以下是模拟容器类型的documentation

答案 2 :(得分:-1)

您只能使用generator(yield关键字)读取值而不能写入