cs9*_*s95 22 python arrays indexing numpy
我正在对2D列表和numpy数组进行一些实验.由此,我提出了3个问题,我很想知道答案.
首先,我初始化了一个2D python列表.
>>> my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用元组索引列表.
>>> my_list[:,]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not tuple
Run Code Online (Sandbox Code Playgroud)
由于解释器抛出一个TypeError而不是一个SyntaxError,我猜测它实际上可以这样做,但是python本身并不支持它.
然后我尝试将列表转换为numpy数组并执行相同的操作.
>>> np.array(my_list)[:,]
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
Run Code Online (Sandbox Code Playgroud)
当然没问题.我的理解是,其中一个__xx__()方法已被覆盖并在numpy包中实现.
Numpy的索引也支持列表:
>>> np.array(my_list)[:,[0, 1]]
array([[1, 2],
[4, 5],
[7, 8]])
Run Code Online (Sandbox Code Playgroud)
这提出了几个问题:
__xx__方法有numpy覆盖/定义来处理花哨的索引?(额外的问题:为什么我的时间显示python2中的切片比python3慢?)
sen*_*rle 23
你有三个问题:
__xx__方法有numpy覆盖/定义来处理花哨的索引?索引操作符[]是重写的使用__getitem__,__setitem__和__delitem__.编写一个提供一些内省的简单子类会很有趣:
>>> class VerboseList(list):
... def __getitem__(self, key):
... print(key)
... return super().__getitem__(key)
...
Run Code Online (Sandbox Code Playgroud)
我们先做一个空的:
>>> l = VerboseList()
Run Code Online (Sandbox Code Playgroud)
现在填写一些值.请注意,我们还没有覆盖,__setitem__所以没有任何有趣的事情发生:
>>> l[:] = range(10)
Run Code Online (Sandbox Code Playgroud)
现在让我们来一个项目.索引0将是0:
>>> l[0]
0
0
Run Code Online (Sandbox Code Playgroud)
如果我们尝试使用元组,我们会收到错误,但我们先看到元组!
>>> l[0, 4]
(0, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in __getitem__
TypeError: list indices must be integers or slices, not tuple
Run Code Online (Sandbox Code Playgroud)
我们还可以了解python如何在内部表示切片:
>>> l[1:3]
slice(1, 3, None)
[1, 2]
Run Code Online (Sandbox Code Playgroud)
你可以用这个对象做更多有趣的事情 - 试一试!
这很难回答.思考它的一种方式是历史:因为numpy开发人员首先考虑它.
在1991年第一次公开发布时,Python没有numpy库,并且要创建一个多维列表,你必须嵌套列表结构.我认为早期的开发人员 - 特别是Guido van Rossum(GvR) - 认为保持简单是最好的,最初.切片索引已经相当强大.
然而,不久之后,人们对使用Python作为科学计算语言的兴趣越来越大.1995年至1997年间,许多开发人员合作开发了一个名为" numeric早期前身"的图书馆numpy.虽然他不是主要的贡献者,numeric或者numpyGvR与numeric开发人员协调,但是扩展了Python的切片语法,使得多维数组索引更容易.后来,又numeric出现了另一种叫做numarray; 并于2006 numpy年创建,融合了两者的最佳功能.
这些库功能强大,但它们需要大量的c扩展等等.将它们放入基础Python发行版会使它变得笨重.尽管GvR确实增强了切片语法,但是为普通列表添加花哨的索引会大大改变它们的API - 并且有点冗余.鉴于已经可以与外部图书馆进行花哨的索引,这样做的好处并不值得.
这种叙述的部分内容都是推测性的,说实话.1我真的不认识开发者!但这是我做出的同样决定.事实上...
虽然花哨的索引非常强大,但我很高兴它甚至不是今天的vanilla Python的一部分,因为这意味着你在使用普通列表时不必非常努力.对于许多任务,你不需要它,它所带来的认知负荷是很重要的.
请记住,我在谈论强加给读者和维护者的负担.你可能是一个天才的天才,可以在你的头脑中做5-d张量产品,但其他人必须阅读你的代码.保持花哨的索引numpy意味着人们不会使用它,除非他们诚实地需要它,这使得代码更易于阅读和维护.
有可能.这绝对是环境依赖的; 我在机器上看不出相同的区别.
1.叙述的部分不是推测性的,是从科学与工程计算特刊(2011年第13卷)中的简短历史中得出的.
my_list[:,] 由口译员翻译成
my_list.__getitem__((slice(None, None, None),))
Run Code Online (Sandbox Code Playgroud)
就像使用调用函数一样*args,但是需要将:符号转换为slice对象。没有,它将通过slice。随着,它通过一个元组。
该列表__getitem__不接受元组,如错误所示。数组__getitem__可以。我相信通过元组和创建切片对象的功能是为numpy(或其前身)添加了便利。元组符号从未添加到列表中__getitem__。(有一个operator.itemgetter类允许使用某种形式的高级索引,但在内部它只是一个Python代码迭代器。)
使用数组,您可以直接使用元组符号:
In [490]: np.arange(6).reshape((2,3))[:,[0,1]]
Out[490]:
array([[0, 1],
[3, 4]])
In [491]: np.arange(6).reshape((2,3))[(slice(None),[0,1])]
Out[491]:
array([[0, 1],
[3, 4]])
In [492]: np.arange(6).reshape((2,3)).__getitem__((slice(None),[0,1]))
Out[492]:
array([[0, 1],
[3, 4]])
Run Code Online (Sandbox Code Playgroud)
查看numpy/lib/index_tricks.py文件中的示例,您可以使用这些有趣的东西__getitem__。您可以使用
np.source(np.lib.index_tricks)
Run Code Online (Sandbox Code Playgroud)
在嵌套列表中,子列表独立于包含列表。容器仅具有指向内存中其他位置的对象的指针:
In [494]: my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [495]: my_list
Out[495]: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [496]: len(my_list)
Out[496]: 3
In [497]: my_list[1]
Out[497]: [4, 5, 6]
In [498]: type(my_list[1])
Out[498]: list
In [499]: my_list[1]='astring'
In [500]: my_list
Out[500]: [[1, 2, 3], 'astring', [7, 8, 9]]
Run Code Online (Sandbox Code Playgroud)
在这里,我更改第二项my_list;它不再是列表,而是一个字符串。
如果我申请[:]一份清单,我只会得到一份浅表副本:
In [501]: xlist = my_list[:]
In [502]: xlist[1] = 43
In [503]: my_list # didn't change my_list
Out[503]: [[1, 2, 3], 'astring', [7, 8, 9]]
In [504]: xlist
Out[504]: [[1, 2, 3], 43, [7, 8, 9]]
Run Code Online (Sandbox Code Playgroud)
但在xlist中更改列表的元素的确会在中更改相应的子列表my_list:
In [505]: xlist[0][1]=43
In [506]: my_list
Out[506]: [[1, 43, 3], 'astring', [7, 8, 9]]
Run Code Online (Sandbox Code Playgroud)
对我来说,这显示了n维索引(对于numpy数组实现)对于嵌套列表没有意义。嵌套列表只有在其内容允许的范围内才是多维的。它们没有结构或语法上的多维性。
[:]在列表上使用两个不会产生深层副本,也不会沿嵌套工作。它只是重复浅拷贝步骤:
In [507]: ylist=my_list[:][:]
In [508]: ylist[0][1]='boo'
In [509]: xlist
Out[509]: [[1, 'boo', 3], 43, [7, 8, 9]]
Run Code Online (Sandbox Code Playgroud)
arr[:,]只是让一个view的arr。view和之间的区别copy是理解基本索引和高级索引之间区别的一部分。
所以alist[:][:]和arr[:,]是不同的,但是是制作列表和数组副本的基本方法。既不计算任何内容,也不迭代元素。因此,时间比较不会告诉我们太多。
| 归档时间: |
|
| 查看次数: |
2647 次 |
| 最近记录: |