python 数组间隔取值_Python进阶04-序列切片和增量的高级用法

python 数组间隔取值_Python进阶04-序列切片和增量的高级用法_第1张图片

切片的高级用法

为什么忽略最后一个元素

在切片的操作中都不会包含最后一个元素,比如b[0:3]:b[0],b[1],b[2]。这样做的目的是:符合 Python、C 和其他语言里以 0 作为起始下标的传统。 好处有: - 当只有最后一个位置信息时,我们也可以快速看出切片和区间里有几个元素array[:5],返回5个元素 - 当起止位置信息都可见时,计算出切片和区间的长度:a[1:4],4-1=3,count = stop-start - 利用任意一个下标来把序列分割成不重叠的两部分:a[:x],a[x:]

l = [1,2,3,4,5,6,7]
#只有最后一个位置信息
print(l[:4])
#当起止位置信息都可见
print(l[2:4])
# 分割成不重叠
print(l[:2])
print(l[:2])
print(l[:3])
print(l[:3])
[1, 2, 3, 4]
[3, 4]
[1, 2]
[1, 2]
[1, 2, 3]
[1, 2, 3]

对对象进行切片

s[a:b:c] 的形式对 s 在 a 和 b 之间以 c 为间隔取值。c 的值还可以为负,负值意味着反向取值。 a:b:c 这种用法只能作为索引或者下标用在 [] 中来返回一个切片对象:slice(a, b, c) 给切片命名:SKU = slice(0,6)

#间隔取值切片
s = 'feifei'
# 从第一个取到最后一个,间隔为3
print(s[::3])
# 反向从第一个取到最后一个,间隔为0
# 这个可以用来反向
print(s[::-1])
print(s[::-2])
ff
iefief
ife
#利用切片对象来实现数据的解析

invoice = """ 
... 0.....6................................40........52...55........
... 1909  Pimoroni PiBrella                    $17.50    3    $52.50 
... 1489  6mm Tactile Switch x20                $4.95    2     $9.90 
... 1510  Panavise Jr. - PV-201                $28.00    1    $28.00 
... 1601  PiTFT Mini Kit 320x240               $34.95    1    $34.95
..."""

SKU = slice(0,6)
DESCRIPTION = slice(6,40)
UNIT_PRICE = slice(40,52)
QUANTITY = slice(52,55)
ITEM_TOTAL = slice(55,None)
line_items = invoice.split('n')[2:]
for item in line_items:
    #print(item)
    print(item[UNIT_PRICE],item[DESCRIPTION])
$17.5 09  Pimoroni PiBrella             
        $4.9 89  6mm Tactile Switch x20        
       $28.0 10  Panavise Jr. - PV-201         
       $34.9 01  PiTFT Mini Kit 320x240

多维切片和省略

多维切片 [] 运算符里还可以使用以逗号分开的多个索引或者是切片
二维的 numpy.ndarray 就可以用 a[i,j] 这种形式来获取,抑或是用 a[m:n,k:l]的方式来得到二维切片

Python 内置的序列类型都是一维的,因此它们只支持单一的索引,成对出现的索引是没有用的。

省略 省略(ellipsis)的正确书写方法是三个英语句号(...) - 也可以用在函数的参数清单中,比如 f(a, ..., z),或 a[i:...] - 在 NumPy 中,... 用作多维数组切片的快捷方式。如果 x 是四维数组,那么 x[i, ...] 就是 x[i, :, :, :] 的缩写。

给切片赋值

把切片放在赋值语句的左边,或把它作为 del 操作的对象,我们就可以对序列进行嫁接、切除或就地修改操作。

注意 如果赋值的对象是一个切片,那么赋值语句的右侧必须是个可迭代对象。即便只有单独一个值,也要把它转换成可迭代的序列。

# 给切片赋值
l = list(range(10))
print(l)
l[2:5] = [20,30]
print(l)
del l[5:7]
print(l)
l[3::2] = [11,22]
print(l)
l[2:5] = [100]
print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 20, 30, 5, 6, 7, 8, 9]
[0, 1, 20, 30, 5, 8, 9]
[0, 1, 20, 11, 5, 22, 9]
[0, 1, 100, 22, 9]

对序列使用+和*

通常 + 号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,Python 会新建一个包含同样类型数据的序列来作为拼接的结果。

如果想要把一个序列复制几份然后再拼接起来,更快捷的做法是把这个序列乘以一个整数。

+ 和 * 都遵循这个规律,不修改原有的操作对象,而是构建一个全新的序列。

# 序列使用+和*
l1 = [1,2,3]
l2 = [4,5,6]
print(l1+l2)
print(5 * 'abcd')
[1, 2, 3, 4, 5, 6]
abcdabcdabcdabcdabcd

建立由列表组成的列表

有时我们会需要初始化一个嵌套着几个列表的列表,最好的选择是使用列表推导.

列表推导写法board = [['_'] * 3 for i in range(3)]

迷惑的写法 weird_board = [['_'] * 3] * 3

两者的区别: - 列表推导的写法,表示每次循环都会新建一个列表元素 - 迷惑的写法,表示同一个元素复制3次,实际上是指向同一个列表 - 迷惑的写法中,当需要修改的时候,会同时被修改,因为这 3 个引用指向的都是同一个列表

# 使用列表推导来创建嵌套列表
# ['_'] * 3 每次循环都创建一次,
board = [['_'] * 3 for i in range(3)]
print(board)
board[1][2] = 'X'
print(board)
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
[['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]
# 列表推导等同做法
borad = []
for i in range(3)
    sub = ['_'] * 3 # 每次都新建3个元素
    borad.append(sub)
# 迷惑的写法
weird_board = [['_'] * 3] * 3
print(weird_board)
weird_board[1][2] = 'X'
print(weird_board)
[['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
[['_', '_', 'X'], ['_', '_', 'X'], ['_', '_', 'X']]
# 迷惑的写法等同做法
borad = []
sub = ['_'] * 3 # 只新建一次
for i in range(3)
    borad.append(sub) #每次都添加同一个引用

序列的增量赋值(+=/*=)

可变序列与不可变序列的增量赋值

增量赋值:对第一个对象进行操作,如下例子,对a进行操作。a += b

增量赋值的原理: 使用的特殊方法是 iadd(用于“就地加法”),如果没有实现这个方法就会退一步调用add方法。 对于上面的例子: - 如果a实现了__iadd__ 方法,就会调用该方法,如果a是可变序列,就像调用了 a.extend(b) 一样 - 如果a没有实现__iadd__ 方法,a += b 这个表达式的效果就变得跟 a = a + b,这样a+b会创建一个新的对象,然后赋值给a,a就关联一个新的对象地址了。

总体来讲,可变序列一般都实现了 iadd 方法,因此 += 是就地加法。而不可变序列根本就不支持这个操作,对这个方法的实现也就无从谈起。对不可变序列进行重复拼接操作的话,效率会很低,因为每次都有一个新对象。

# 可变序列的 *=
l = [1,2,3]
print(id(l))
l *=2
print(l)
print(id(l)) #id并未改变说明就地增加

t = (1,2,3)
print(id(t))
t *=2
#t +=t
print(t)
print(id(t)) # id被修改,创建了新的对象
2163791378760
[1, 2, 3, 1, 2, 3]
2163791378760
2163788018744
(1, 2, 3, 1, 2, 3)
2163791314280

关于+=的谜题

对于如下的例题,出现的结果如下:

t = (1,2,[30,40])
t[2] +=[50,60]
  • t 变成 (1, 2, [30, 40, 50, 60])。
  • 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 异常。

如何避免该错误: - 不要把可变对象放在元组里面。 - 增量赋值不是一个原子操作。我们刚才也看到了,它虽然抛出了异常,但还是完成了操作。 - 写成 t[2].extend([50, 60]) 就能避免这个异常

t = (1,2,[30,40])
t[2] +=[50,60] 
#print(t)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

 in 
      1 t = (1,2,[30,40])
----> 2 t[2] +=[50,60]
      3 print(t)


TypeError: 'tuple' object does not support item assignment
print(t)
(1, 2, [30, 40, 50, 60])

分享关于人工智能,机器学习,深度学习以及计算机视觉的好文章,同时自己对于这个领域学习心得笔记。想要一起深入学习人工智能的小伙伴一起结伴学习吧!扫码上车!

python 数组间隔取值_Python进阶04-序列切片和增量的高级用法_第2张图片

你可能感兴趣的:(python,数组间隔取值)