首页 > 编程语言 >python基础一:python列表基础和一些经典使用案例

python基础一:python列表基础和一些经典使用案例

时间:2024-03-24 22:35:00浏览次数:30  
标签:10 ac python 元素 基础 列表 lst 拷贝

1. 写在前面

好久没有更新python这一块的内容了, 所以今天整理一块python的内容。今天整理的内容是python里面的列表, 作为在python中非常常见的数据类型, 尝试用一篇文章来整理其常用的操作,方便以后查看使用。 目前可能不全,以后遇到列表相关的操作都放到这篇文章里面来。

首先从列表的基础操作开始, 看一下什么是python列表, 列表背后的内存组织, 然后介绍列表里面的常用操作, 像列表的添加, 删除,切片等。 接下来会介绍点深浅拷贝的知识和可变不可变对象。 最后整理常用的列表使用案例。

这次整理列表, 会从纯使用的角度去整理, 关于列表的理论知识和细节知识, 这里不做整理。

知识框架:

  • 列表的基础操作(添加, 删除, 切片, 索引, 遍历等)
  • 深浅拷贝和可变不可变
  • 列表常用的使用小例子

ok, let’s go!

2. 列表的基础操作

关于list, 它是python中非常重要的一种数据类型, 常用的创建方式会有两种: []和list(), 下面我们先尝试创建一个列表:

lst = [1, 3, 5]   # lst就是一个列表
# lst = list((1, 3, 5))

我们看看这行代码在内存中是什么样子的:

 是有一块内存空间存放[1, 3, 5], 然后把这块内存空间的首地址给了list。注意,这个地方右边是开着的, 和(1,3,5)还不一样, 后者表示元组, 在内存里面是这样:

 


元组也是python中容器型的一种, 和list不同的是, list是一种可变对象, 而元组是一种不可变对象。

2.1 列表的常用操作

创建完列表之后,我们要会使用,这里介绍一些基本的使用,比如查看列表的元素个数, 遍历列表看元素和及其类型, 列表的添加, 删除, 切片,索引。 下面就来看看:

 1 # 创建一个列表
 2 lst = [1, 'xiaoming', 29.5, '17382348927']      # 列表里面元素类型不一定一样
 3 
 4 print(len(lst))   # len函数返回列表的元素个数, 非常常用
 5 
 6 # 列表的索引 由于下标是0-len(st)-1, 所以通过下标就可以访问某个元素
 7 lst[2]   # 这个就是29.5
 8 
 9 
10 # 遍历列表
11 for _ in lst:     # 这行代码就可以遍历列表查看每个元素的类型
12     print(f"{_}的类型为{type(_)}")
13 
14 ## 结果
15 1的类型为<class 'int'>
16 xiaoming的类型为<class 'str'>
17 29.5的类型为<class 'float'>
18 17382348927的类型为<class 'str'>

 

列表作为一种可变对象, 我们是可以在里面添加和删除元素的, 关于列表的添加, 常用的方式有三种: append, extend, insert。

# append方式从列表的尾部添加元素
lst = [1, 'xiaoming', 29.5, '17382348927']
lst.append('hello')   #[1, 'xiaoming', 29.5, '17382348927', 'hello']
lst.append(['hello', 'world'])  #  #[1, 'xiaoming', 29.5, '17382348927', 'hello', ['hello', 'world']]  
# 上面的第二个是列表里面又加了个列表元素

# extend也是从列表尾部添加元素, 但是和append又有些区别
lst.extend(['hello', 'world'])  # [1, 'xiaoming', 29.5, '17382348927', 'hello', 'world]  
# 注意看区别, extend的时候,是只要后面列表里面的元素, 不是把列表加进去

# insert 在指定位置添加元素
lst.insert(1, 10)
# [1, 10, 'xiaoming', 29.5, '17382348927']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

上面的都比较简单, 做简单回顾。

关于列表的删除常用的方式: pop和remove

lst = [1, 'xiaoming', 29.5, '17382348927']

# pop 默认是从尾部删除元素并返回
lst.pop()   # 这个是'17382348927' 
# 执行了上面这句代码之后, lst变成了[1, 'xiaoming', 29.5], 当然pop也可以指定位置删除元素
lst.pop(1) 

# remove()删除指定元素
lst.remove('xiaoming')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

关于索引的切片, 这里不多说, 简单演示:

a = [i for i in range(1, 10)]
print(a)
print(a[::-1])        # 列表翻转  这个很实用
print(a[:-1])
print(a[1:5:2])
print(a[::-3])

## 结果
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 4]
[9, 6, 3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. 关于深浅拷贝和可变不可变

先抛开深浅拷贝, 我们先来看一个列表的例子:

# 列表的创建
lst2 = ['001','2019-11-11',['三文鱼','电烤箱']]
  • 1
  • 2

这个列表看起来很简单, 但是内部怎么组织的呢?
在这里插入图片描述
现在就知道了, 列表里面套列表的时候, 在内存的角度到底是如何组织的。 这时候,我们把里面那个列表给赋值到一个新的变量上面去:

# 索引
sku = lst2[2]   # ['三文鱼', '电烤箱']
  • 1
  • 2

这时候内存是这样子的:
在这里插入图片描述
就是sku也指向到了里面的这个列表中。 这时候, 很明显,我们尝试修改sku指向的列表, 那么lst[2]肯定也会变:

sku.append('烤鸭')   

# 这时候
sku  ['三文鱼', '电烤箱', '烤鸭']
lst2  ['001','2019-11-11',['三文鱼','电烤箱', '烤鸭']]
  • 1
  • 2
  • 3
  • 4
  • 5

也就是这种情况下, 修改sku会导致lst2本身也会改变。 看内部原理图就非常容易理解, 那么有没有一种方式,我改sku的时候,不改变lst2本身呢?

3.1 深浅拷贝

浅拷贝可以帮助我们完成上面的要求, 浅拷贝.copy(), 把lst2[2]进行拷贝一份, 这时候就发现sku变量与lst2[2]指向的对象就不是一个了。

sku_deep = lst2[2].copy()
sku_deep     # ['三文鱼', '电烤箱']
  • 1
  • 2

虽然内容是一样, 但看内存:
在这里插入图片描述
这时候很显然, 修改sku_keep就不会影响lst2的内容了。 那么浅拷贝和深拷贝有啥区别呢?

上面这个例子可能还看不出区别, 但是下面这个例子就非常看出事情:

# 再创建一个新的列表,也是列表套列表
a = [1, 2, [3, 4, 5]]
ac = a.copy()   # ac是a的一个浅拷贝

# 我们改一下ac的值
ac[0] = 10   
print(a[0], ac[0])   # 1 10    确实实现了拷贝, a和ac分开了

# 但是真的分的彻底吗?  我们改一下ac的值,但这次该里面那个列表
ac[2][1] = 40
print(a[2][1], ac[2][1]) # 40 40 我们发现了啥?  竟然改ac里面列表的时候a里面的列表也跟着变了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

上面例子就说明了浅拷贝,并没有拷贝的那么彻底, 像这种列表套列表的情况, 浅拷贝仅仅拷贝了第一层而已, 看个图就明白了:
在这里插入图片描述
这个图很清晰的说明了上面的那两个变化情况。 原来浅拷贝之后, a[2]和ac[2]依然指向了同一块空间。 类似于藕断丝连。 浅拷贝之后, 我弄一块新内存放外面的列表, 但是列表里面再有列表的话, 我不管

那么深拷贝是怎么回事呢? 可能你也想到了, 那就是断的彻底。 即使列表里面套列表, 当我深拷贝之后, 我弄一块内存放外面的表, 同时如果列表里面有列表, 我也会弄一块新内存放里面的表。看下面的例子和图:

from copy import deepcopy

a = [1, 2, [3, 4, 5]]
ac = deepcopy(a)
ac[0] = 10
ac[2][1] = 40
print(a[0], ac[0])   # 1 10 
print(ac[2][1], a[2][1])    # 40 4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

深拷贝是deepcopy(), 深拷贝之后我们发现a和ac就完全没有关系了。
在这里插入图片描述

3.2 关于可变与不可变

这个话题其实在python那里尝试整理了一下, 这里再用内部图的方式重新理解一下, 就拿列表和元组来看即可, 看看这个可变和不可变到底啥意思?可变和不可变是一对很微妙的概念

我们知道,列表是可变对象, 那么这个可变是啥意思呢? 我们建立一个列表看一下:

# 创建一个列表
a = [1, 3, [5, 7], 9, 11, 13]   
  • 1
  • 2

上面的a是一个普通列表, 但是又不算一个很普通的列表,因为里面还有一个列表, 我们看看这个的内部图:
在这里插入图片描述
那么什么是可变呢? 这个意思是a指向的对象本身是可以变得, 比如我们在a中删除元素: a.pop()
在这里插入图片描述
是不是a指向的对象本身变了? 如果没看清楚, 我们再像a里面添加元素, a.insert(3, 8)
在这里插入图片描述
所以对于列表而言, 它能添加和删除元素, 所以是可变的。 但注意是本身可变。 如果我执行这一步操作:a[2].insert(1, 6)
在这里插入图片描述
这个如果我们打印a的话, 也会发现a变了, 但是,这个要注意, 这个不能说明a是可变的, 因为a指向的对象本身并没有变, 变得只是a[2]指向的对象, 只能说a里面的元素有可变的, 理解这一点非常重要, 为啥呢? 我们下面看看元组吧。

我们知道,元组是不可变对象, 但是有时候, 我们也能看似改变它的元素:

a =(1,3,[5,7],9,11,13)
  • 1

依然是上面的那些元素, 只是把[]换成(), 这时候a就是一个元组了。 我们看看内部结构:
在这里插入图片描述
其实, 看元组本身会发现右边是封闭的了。 这时候我们依然a[2].insert(1, 6), 这个时候我们同样也会观察到a里面的元素有变化。
在这里插入图片描述
但是, 我们看a指向的对象本身, 其实没有变, a内元素也没有发生增减, 长度还是6, 所以对于不可变对象而言, 一旦创建后,长度就不能发生改变, 但是允许里面的元素有可变对象。

所以对于list而言, 列表长度有增有减,对象本身会发生改变, 所以它是可变的, 而tuple而言, 允许里面的元素可变,但是它本身不会发生改变。 所以它是不可变对象。

说了这么多,不知道听懂了没有。

4. list的经典使用案例

下面的这些例子非常经典实用, 不管是刷题还是应用中其实很常见, 顺序不分先后。

  1. 判断list里面有无重复元素

    def is_duplicated(lst):
        return len(set(lst)) != len(lst)
    
    a = [1, 2, 3, 3]
    is_duplicated(a)
    
    • 1
    • 2
    • 3
    • 4
    • 5
  2. 列表的逆序

    def reverse(lst):
    	return lst[::-1]
    
    • 1
    • 2
  3. 找出列表中重复的元素
    这个就是count计数, 遍历一遍,看看有重复的,加入新的数组

    def find_duplicated(l):
        ret = []
        for item in l:
            if l.count(item) > 1 and item not in ret:
                ret.append(item)
        return ret
    
    a = [1, 2, 3, 2, 1]
    b = find_duplicated(a)    # [1, 2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  4. 去掉列表中最大值最小值,然后计算剩余元素平均值

    def score_mean(lst):
        lst.sort()
        lst2 = lst[1:-1]
        return round((sum(lst2)/len(lst2)), 1)
    
    lst=[9.1, 9.0,8.1, 9.7, 19,8.2, 8.6,9.8]
    score_mean(lst)   # 9.1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个像不像去掉最高分和最低分取平均, 看一下动画演示过程:
    在这里插入图片描述

  5. 获得列表的表头和表尾

    def head(lst):
        return lst[0] if len(lst) > 0 else None    #  这个判断形式要会
    print(head([]))
    print(head([1, 2, 3]))
    
    def tail(lst):
        return lst[-1] if len(lst) > 0 else None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  6. 获得列表中出现次数最多的元素
    这个还是很实用的, 寻找众数有没有? 如果列表里面只有一个元素出现的次数最多, 那么可以用max内置函数, 里面的key设置为元素的个数比较。

    def mode(lst):
        if not lst:
            return None
        return max(lst, key=lambda v: lst.count(v))   # v 在 lst 的出现次数作为大小比较的依据
    
    a = [1, 2, 3,4, 2]
    mode(a)    # 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果众数不止一个, 那么这时候就需要获得这个众数之后, 得到它出现的次数, 遍历列表,把次数相同的返回:

    # 如果是有多个元素的时候
    def mode(lst):
        if not lst:
            return None
        
        max_freq_elem = max(lst, key=lambda v: lst.count(v))
        max_freq = lst.count(max_freq_elem)   # 出现最多的次数
        ret = []
        for i in lst:
            if lst.count(i) == max_freq and i not in ret:
                ret.append(i)
        
        return ret
    
    a = [1, 2, 3, 4, 3, 2]
    mode(a)   # [3, 2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  7. 返回更长的列表
    就是多个列表, 得到长度最长的那个。 在这里我们看一下max内部到底是咋工作的。

    def max_len(*lists):
        return max(*lists, key=lambda v: len(v))   # v 代表一个 list,其长度作为大小比较的依据
    
    r = max_len([1, 2, 3], [4,5], [5])
    r    # [1, 2, 3]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这个*可以匹配多个参数, 记不记得函数的可变参数? 在python基础里面整理过的。 这里就是把列表都传进去, 然后根据max函数,返回最长的列表, 可以看到这个地方的key表示的list的长度。 看一下内部是怎么实现的:
    在这里插入图片描述

  8. 洗牌数据shuffle

    from random import shuffle, randint
    lst = [1, 2, 3]
    shuffle(lst)
    lst
    
    • 1
    • 2
    • 3
    • 4

    shuffle可以打乱列表, 当然如果是数组的话, 可以用permutation:

    index = np.random.permutation(3)        # 这个是数组的随机洗牌
    a = np.array(lst)
    a = a[index]
    a
    
    • 1
    • 2
    • 3
    • 4

    这些在打乱样本的时候非常实用。

  9. 生成元素对

    a = [i for i in range(10)]
    list(zip(a[:-1], a[1:]))
    
    #
    [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这个在取样的时候也有时候会用到

  10. 斐波那契数列

    def fibonacci(n):
        if n <= 1:
            return [1]
        fib = [1, 1]
        while len(fib) < n:
            fib.append(fib[len(fib)-1] + fib[len(fib)-2])
        
        return fib
    
    fibonacci(5)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    当然,这个方法耗费内存,也不高效, 所以还可以更高效。 用生成器。

    # 上面的方法不高效, 生成器会更简洁和节省内存
    def fibonacci(n):
        a, b = 1, 1
        for _ in range(n):
            yield a          # 遇到yield之后, 返回,下次再进入函数体, 从yield中的下一句执行
            a, b = b, a+b
    
    list(fibonacci(5))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

今天的内容就先整理这么多, 后期会把列表中的一些实用操作都整理到一块来, 便于学习和查找。

标签:10,ac,python,元素,基础,列表,lst,拷贝
From: https://www.cnblogs.com/szmtjs10/p/18093237

相关文章

  • 蟒蛇书入门学习笔记(3)Python列表
    列表列表是一种数据结构,用于储存一系列有序的数据,可以根据需要动态地增加或删除元素。列表在很多编程语言中都有内置的实现,常用的操作包括插入、删除、修改和查找元素。1.列表的表示列表可以包含字符、数字等等元素,一般来说用表示复数的名称(如letters,digits,names)命名列表,用......
  • python数据挖掘实验一:数据分析及可视化应用
    1.导入pandas包importpandasaspd2.根据给定的原始数据集创建一个DataFrame类型对象dfdata={'id':[10001,10002,10003,10004,10005,10006,10007,10008,10009,10010],'name':['LY','CE','ZS','LS','WU','......
  • Python爬虫--2
    本节笔记获取豆瓣网站内容记录文件创建时间文件→设置→编辑器→文件和代码模板中找到PythonScript在输入界面输入"#日期:${DATE}"#文件:${NAME}新建一个Python文件,显示了此文件创建时间和文件名字一.单页获取1.获取电影名字网页URL:https://movie.douban.com/top250......
  • Python 中的抽象类和接口类
    【抽象类】抽象类是一个特殊的类,只能被继承,不能被实例化。它主要用于作为其他类的基类或模板。抽象类可以包含抽象方法和具体方法。在抽象类中定义的抽象方法必须在子类中进行实现。fromabcimportabstractmethod,ABCMetaclassFruit(metaclass=ABCMeta):@abstractme......
  • 【系统架构师】-第5章-软件工程基础知识
    P(Plan)——软件规格说明。规定软件的功能及其运行时的限制。D(Do)——软件开发。开发出满足规格说明的软件。C(Check)——软件确认。确认开发的软件能够满足用户的需求。A(Action)——软件演进。软件在运行过程中不断改进以满足客户新的需求。生命周期:经历从需求分析、......
  • C#基础第一阶段
    开始|--Properties  项目工程的配置目录,例如:启动...|--引用      整个C#程序需要引用第三方技术时,放在这里|--App.config  整个应用程序的配置文件|--progress.cs  程序启动时执行的C#脚本文件以上目录为C#程序的项目工程在工程目录......
  • 2024-3-24刷题的一个小错误,居然这么基础-_-!!
    力扣刷题刷到简单二分查找时,一运行代码就提示超时,怎么就超时了?反反复复几次,发现(right-left)>>1+left这一步需要在移位运算部分加括号,查了一下,基础中的基础是:移位运算优先级低于“+-*/”我要裂开了……真的好基础!!! intsearchInsert(int*nums,intnumsSize,inttarget){......
  • Python好库
    Python好库一、有序列表fromsortedcontainersimportSortedListsl=SortedList([1,3])sl.add(-1)sl.remove(3)print(sl)print(sl.bisect_left(1))print(sl.bisect_right(3))"""SortedList([-1,1])12"""二、排列组合fromitertoolsimpor......
  • 【Python】可视化Python库的依赖关系
    这里主要用了两个库:pipdeptree和pyecharts。pipdeptree用来解析所有库的依赖关系。pyecharts用来显示依赖的网络关系。通常的方法应该是通过输入下面命令:pipdeptree--json-tree>pkg.json得到关系树文件,然后解析该文件并在pyecharts显示即可。不过我不想解析json文件了......
  • 计算机基础知识问答:计算机网络
    计算机网络以OSI体系为例讲解计算机网络的各层协议及作用?七层网络体系结构各层的主要功能:应用层:为应用程序提供交互服务。在互联网中的应用层协议很多,如域名系统DNS,支持万维网应用的HTTP协议,支持电子邮件的SMTP协议等。表示层:主要负责数据格式的转换,如加密解密、转换翻......