本文主要讲解了python中列表的使用 本文为自学B站上鱼C的python课程随手做的笔记。 如有问题,欢迎大家批评指正 原视频链接:https://www.bilibili.com/video/BV1c4411e77t?p=8
(介绍顺序为从0开始理解向,从问题开始最后会说到两者区分)
作用:用于检验两个变量是否指向同一个对象的一个运算符。 示例: NB:出现以上情况是因为python对于不同对象的存储机制是不一样的。 对于字符串,由于字符串是不可变的,存储时是在内存中开辟一个位置来存放就好。如果有多个变量名指向一个字符串,那么两者的关系应是: 对于列表,列表是可变的,尽管例子中x,y两个列表是一样的,但是python还是需要为它们开辟出两个不同的位置来存放,即:
导致改了多维列表中一个列表中的元素,其他列表的元素都发生了改动。 演示: 先用创建A,B两个看似相同的多维列表: 对多维列表中的一个元素进行修改: 我们发现,A按照我们的想法只改动了一个元素,但是B却每一维的第二个元素都发生了变化。 我们用is来判断一下: 所以A中的三维的三个列表是分别存储的三个不同列表,B中的是同一个列表的多次引用。即二者的在python中的内存布局应该是: B试图通过乘号对列表进行拷贝,但事实上只是拷贝了同一个列表的引用。
变量不是一个盒子,当赋值运算发生的时候,python并不是将数据放到变量里去,而是将变量与数据进行挂钩,这个行为我们称之为引用。将一个变量赋值给另一个变量就是将一个变量的引用传递给另一个变量。 我们发现通过赋值产生的两个列表,当x发生变化时,y也会改变。 两者内存示意图:
所以要想得到两个独立的列表,就需要用拷贝。
此时改变x,y并不会发生改变。这里copy方法拷贝的是整个列表对象,而不仅仅是引用。 示意图:
NB: 浅拷贝只是拷贝了外层的对象,如果包含嵌套对象的话,那么拷贝的只是其引用。所以在拷贝多维列表时,浅拷贝就可能出现问题,而深拷贝可以解决这个问题。 (浅拷贝处理一维列表是没有问题的) 示例,处理多维列表时,浅拷贝会出现的问题:
2. 深拷贝: 深拷贝在将原对象拷贝以后,也将对象中所有引用的子对象一并进行了拷贝。 深拷贝需要借助copy模块里的deepcopy函数。
(1)copy 函数 (浅拷贝) 可以拷贝列表、字符串、元组等: copy 实现浅拷贝:
(2)deepcopy 函数 (深拷贝) deepcopy 实现深拷贝: 这里的深拷贝内存示意图:
(1)基本语法
[expression for target in iterable]
(1)示例: 理解:for循环的语句每次循环都有一个i,列表最终存放的元素取决于for循环语句左侧的expression表达式。 比如以list3为例,for循环把字符串“abcde”中每个字母拿出来,然后列表最终存放的元素是表达式i*2,即每个字母重复一次 (2)更多示例 (嵌套列表): 用列表推导式生成嵌套列表: 2. b. 添加一个用于筛选的if分句
[expression for target in iterable if condition]
示例: 执行顺序: 应该是先执行for语句,再if,最后再i 比如下面这个例子验证执行顺序: 处理字符串: 3. c. 列表推导式实现嵌套
[expression for target1 in iterable1 for target2 in interable2 .... for targetN in interableN]
示例: 注意外层循环放在前面,嵌套内层循环放在后面。 4. d. 列表推导式实行多个嵌套且每个for语句都可以加一个if 条件
[expression for target1 in iterable1 if condition1 for target2 in iterable2 if condition2 ...... for targetN in iterableN if conditionN]
(2) 列表推导式和for 循环的差别: for 和列表推导式这里都产生了相同的列表,但是两者本质上有区别: for: 是通过迭代来逐个修改列表里的元素(电视坏了,我们选择去修一下) 列表推导式:直接产生一个新的列表,再赋值回原先的变量名(电视坏了,直接换一个电视) 两者效果多相同,但本质上是不同的。for循环要比列表推导式运算速度上慢很多。
(3) 程序设计要注意KISS(keep it simple and stupid) 原则,列表推导式的复杂程度要好好把握。不要写太复杂的代码不便于维护,简洁胜于复杂。