06-03线性结构与切片

Posted cishi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06-03线性结构与切片相关的知识,希望对你有一定的参考价值。

线性结构与切片

线性结构

  • 列表、元组、字符串、bytes, bytearray
  • 共同点:都是顺序存储, 顺序访问的, 都是可迭代对象, 都可以通过索引访问

线性结构特征

  • 可迭代
  • len获取长度
  • 可以使用下标操作符通过索引访问
  • 可以切片
例如:可迭代的表现形式
In [1]: for i in [1, 2, 3]:
   ...:     print(i)
   ...:
1
2
3

In [2]: for i in (1, 2, 3):
   ...:     print(i)
   ...:
1
2
3

In [4]: for c in ‘i lve python‘:
   ...:     print(c)
   ...:
i
 
l
v
e
 
p
y
t
h
o
n

函数enumerate

作用:接收一个可迭代对象,返回一个enumerate对象
作用(菜鸟教程):enumerate(sequence, [start=0]) 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

实例:
In [5]: enumerate([1, 2, 3])   # 接收一个可迭代对象,返回一个enumerate对象(这种语句都不知道讲什么鬼)
Out[5]: <enumerate at 0x7fc5a6fa2750>

In [6]: list(enumerate([1, 2, 3]))   # 会得到一个列表
Out[6]: [(0, 1), (1, 2), (2, 3)]

>>>seasons = [‘Spring‘, ‘Summer‘, ‘Fall‘, ‘Winter‘]
>>> list(enumerate(seasons))
[(0, ‘Spring‘), (1, ‘Summer‘), (2, ‘Fall‘), (3, ‘Winter‘)]
>>> list(enumerate(seasons, start=1))       # 下标从 1 开始
[(1, ‘Spring‘), (2, ‘Summer‘), (3, ‘Fall‘), (4, ‘Winter‘)]


enumerate的实现
In [8]: def enumerate(iterator):   # 方式1
   ...:     i = ()
   ...:     for v in iterator:
   ...:         yield i, v
   ...:         i += 1
   ...:

In [9]: def enumerate(interator):    # 方式2
   ...:     ret = []
   ...:     i = ()
   ...:     for v in iterator:
   ...:         ret.append((i, v))
   ...:         i += 1
   ...:     return ret
   ...:

方式1与方式2并不等效, 但是返回的效果是一样的。

iter函数

作用:将一个可迭代对象转换为一个迭代器
两种使用方式:

  • iter(iterable) -> iterator
  • iter(callable, sentinel) -> iterator # sentinel必须是一个可调用对象,当每次调用这个__next__()方法时,都会调用该对象。
In [10]: len(range(5))   # 可迭代对象都可以用len获取长度
Out[10]: 5

iter函数可以将一个可迭代对象转换为一个迭代器
next函数可以读取迭代器的下一个值

In [11]: next(iter(range(5)))   # 一起使用的方式
Out[11]: 0

可迭代对象可以通过 iter 函数转换为迭代器

切片操作

  • 操作对象:都可以通过索引访问的数据类型
  • 操作方式:都是返回一个新的对象,不会对原有数据做更改
    • lst[start:stop] 可以访问这个list一段, 从start开始, 到stop结束, 不包含stop,例如lst[3:7]
      • 当start为0时可以省略
      • 当stop为-0的时候可以省略
      • lst[:]都省略的时候等效于copy
      • 支持负数索引,负数索引实际上可以转换为len(lst) + index
      • 超出范围不报错
        • start超出索引范围:start = 0
        • stop超出索引范围:stop = -0
      • 当start >= stop时,返回空列表
    • lst[start: stop: step] step参数表示一次增加多少
      • lst[8:3:-2] # step为负数的时候,反过来,此时start应该 >= stop
      • lst[::-1] # 只有step, 全面反转
In [15]: lst = list(range(10))

In [16]: lst
Out[16]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [17]: lst[3]   # 可以通过索引访问
Out[17]: 3

lst[start:stop] 可以访问这个list一段, 从start开始, 到stop结束, 不包含stop

In [18]: lst[3:7]    # 从索引3开始, 到索引7结束, 不包含7, 返回新的list, 不会对原有的list做任何修改
Out[18]: [3, 4, 5, 6]

In [19]: lst[:4]       # 当start为0时可以省略
Out[19]: [0, 1, 2, 3]

In [20]: lst[3:]   #  当stop为-0的时候可以省略
Out[20]: [3, 4, 5, 6, 7, 8, 9]

In [21]: lst[:]   # 都省略的时候等效于copy
Out[21]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [22]: lst[-5:-3]   # 可以支持负数索引
Out[22]: [5, 6]

In [23]: lst[:100]   # stop超出索引范围
Out[23]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [24]: lst[-100:]   # stop超出索引范围
Out[24]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [25]: lst[-100:100]   # 同时超出索引范围
Out[25]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

start超出索引范围:start = 0
stop超出索引范围:stop = -0

In [27]: lst[100:]   # 和上两个结论冲突, lst[100:-1]
Out[27]: []

In [28]: lst[:-100]  # 和上两个结论冲突, lst[0:-100]
Out[28]: []

In [29]: lst[100:-100]   # 正向反向都超出的时候
Out[29]: []

In [30]: lst[3:1]   # 当start > stop时,返回空列表
Out[30]: []

In [31]: lst[3:3]   # 当start = stop时,也返回空列表
Out[31]: []

In [32]: lst[3:-1]   # 负数索引, 实际上等于len(lst) + index, 10 + (-1) = 9
Out[32]: [3, 4, 5, 6, 7, 8]

负数索引实际上可以转换为len(lst) + index
当start为0时可以省略, 当stop为-0时可以省略
当stop <= start时, 返回空列表
当start超出索引范围start = 0, 当stop超出索引范围 stop 为-0

In [4]: def slice(lst, start=0, stop=0):
   ...:     if start < 0:
   ...:         start = len(lst) + start
   ...:     if stop <= 0:
   ...:         stop = len(lst) + stop
   ...:     if stop <= start:
   ...:         return []
   ...:     if stop > len(lst):
   ...:         stop = len(lst)
   ...:     if start < 0:
   ...:         start = 0
   ...:     ret = []
   ...:     for i, v in enumerate(lst):
   ...:         if i >= start and i < stop:
   ...:             ret.append(v)
   ...:     return ret
   ...: 

In [5]: slice(lst, -100, 100)
Out[5]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

lst[start: stop: step]   step参数表示一次增加多少

In [3]: lst[3:8:2]
Out[3]: [3, 5, 7]

In [4]: lst
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [5]: lst[8:3:-2]   # step为负数的时候,反过来
Out[5]: [8, 6, 4]

In [2]: lst[::-1]     # 只有step, 全面反转
Out[2]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

In [4]: def slice(lst, start=0, stop=0, step=1):
   ...:     current = start
   ...:     ret = []
   ...:     while current < stop:
   ...:         try:
   ...:             ret.append(lst[current])
   ...:         except IndexError:
   ...:             pass
   ...:         current += step
   ...:     return ret
   ...: 

In [5]: slice(lst, 0, 10, 1)
Out[5]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

当step为负数的时候
In [16]: def slice(lst, start=0, stop=0, step=1):
    ...:     ret = []
    ...:     current = start
    ...:     if step > 0:
    ...:         while current < stop:
    ...:             try:
    ...:                 ret.append(lst[current])
    ...:             except IndexError:
    ...:                 pass
    ...:             current += step
    ...:     if step < 0:
    ...:         while current > stop:
    ...:             try:
    ...:                 ret.append(lst[current])
    ...:             except IndexError:
    ...:                 pass
    ...:             current += step
    ...:     return ret
    ...: 



以上是关于06-03线性结构与切片的主要内容,如果未能解决你的问题,请参考以下文章

Python09线性结构与切片

你知道的Go切片扩容机制可能是错的

Golang切片与函数参数“陷阱”

go——切片

如何通过单击片段内的线性布局从片段类开始新活动?下面是我的代码,但这不起作用

树回归