Python学习笔记--线性结构与切片

定义

目前学习到的数据结构:

  • 列表
  • 元组
  • 字符串
  • bytes
  • bytearray

共同特点:

都是顺序存储,顺序访问的,都是可迭代对象,都可以通过索引访问

这样一类的结构称为:线性结构
线性结构的特点:

  • 可迭代
  • 可以用len方法获取长度
  • 可以使用下标操作符通过索引访问
  • 可以切片

例子如下:

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

for i in 'i smart':
    print(i)
i
    
s
m
a
r
t

enumerate

>>> enumerate((1,2,3))
<enumerate object at 0x000002170E0E0368>
#这里返回了一个可迭代对象

看看可迭代对象是什么:

>>> list(enumerate([1,2,3]))
[(0, 1), (1, 2), (2, 3)]

在这里用代码实现一个enumerate()函数:

#方式一,用yield封装:
def new_enumerate(iterator):
    i = 0
    for v in iterator:
        yield i,v
        i += 1

#方式二,便于理解:
def new_enumerate1(iterator):
    ret = []
    i = 0
    for v in iterator:
        ret.append((i,v))
        i += 1
    return ret

什么时候用到enumerate:同时获取索引和value的时候需要用这个函数。

例子:如果有一个list,这个list里是一个个的用户对象,而你在逻辑里还需要对他们的索引作计算:

>>> users = ['punch', 'xu', 'kidult', 'justin']
>>> for i,user in enumerate(users):
...     print(i,':', user)
...
0 : punch
1 : xu
2 : kidult
3 : justin

迭代器

关于range()函数,用来获取一段范围内的数字,可能是连续的,可能不是连续的。
range(1,10,2),三个参数分别代表:

  • 第一个参数,start:什么位置开始
  • 第二个参数,end:什么位置结束
  • 第三个参数,step:步长,每多少个值向下取一个
>>> list(range(1,10,3))
[1, 4, 7]

next函数是用来迭代可迭代对象的。next函数需要一个迭代器,而iter方法可以转化可迭代对象为迭代器。next不能直接迭代可迭代对象,list是一个可迭代对象,需要iter函数将可迭代话对象转换成迭代器

>>> it = iter(list((1,2,3)))
>>> it
<list_iterator object at 0x000002170E0E3248>
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
#当next将迭代器的元素都迭代过一遍之后,再迭代就会抛出StopIteration异常

可迭代对象可以通过iter函数转换为迭代器,之后迭代器便可用next函数迭代
将list转化为迭代器这种方式,方便我们来获取数据,降低性能消耗。

切片操作

>>> lst = list(range(10))
>>> lst[3]
3

这个操作是通过索引获取列表的具体某一个元素
这个不是切片,切片是选择某一段:

>>> lst[3:7]
[3, 4, 5, 6]

lst是从0开始的连续整数,而索引也是从0开始的,因此索引为3的元素是对应整个列表从左往右的第4个元素。
而索引为7的元素,这里则规定,切片操作是左闭右开的取值范围。从3开始,再7前面一个结束。
:lst[start:stop],可以访问lst从start开始到stop-1结束,不包含stop,并且原地不修改,有返回值。

#当start为0时可以省略:
>>> lst[:4]
[0, 1, 2, 3]
#当想获取最后一个值时可以省略stop参数:
>>> lst[7:]
[7, 8, 9]
#'lst[:]',等效于copy方法
>>> l2 = lst[:]
>>> l2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> lst[0] = 'a'
>>> lst
['a', 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#stop超出索引范围
>>> lst[:1000]
['a', 1, 2, 3, 4, 5, 6, 7, 8, 9]
#start超出索引范围
>>> lst[-100:]
['a', 1, 2, 3, 4, 5, 6, 7, 8, 9]
#start和stop都超出索引范围
>>> lst[-100:100]
['a', 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • start超出索引范围时,start=0
  • stop超出索引范围时,stop=-1
#当start >= stop时,返回空列表
>>> lst[4:3]
[]
#负数索引,实际上等于len(lst)+index,
>>> lst[3:-3]
[3, 4, 5, 6]

用代码实现一遍:

def _slice(lst,start=0,stop=0):
    #判断start和stop小于0时做什么
    if start < 0:
        start = len(lst) + start
    if stop <= 0:
        start = len(lst) +stop
    #这里时判断越界行为
    if stop <= start:
        return []
    if stop > len(lst):
        stop = len(lst)
    #存储切片后的结果
    ret = []
    #这里把元素索引和start、end对应起来
    for i,v in enumerate(lst):
        if i >= start and i < stop:
            ret.append(v)
    return ret

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

>>> lst[3:9:2]
[3, 5, 7]
>>> lst[9:3:-2]
[9, 7, 5]
>>> lst[::-2]
[9, 7, 5, 3, 1]
#下面为小技巧,可直接将列表倒序
>>> lst[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 'a']

实现带step的方法:

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

小结

感觉这一章的知识还是非常实用的。
enumerate这个方法在列表循环的时候也是用的非常多,一次循环获取索引和元素,能够快速实现业务逻辑。
迭代器也是十分重要。用来做懒惰求值,提升代码性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值