Python基础知识4——操作列表

本章内容来自书籍,记录下来仅方便复习,如有侵权,请联系作者删除。

一、遍历整个列表

遍历列表中的所有元素,并对每个元素执行相同的操作。可用Python中的for循环。

names = ['tom','john','mary','jenny']
for name in names:
    print(name)
运行结果:
tom
john
mary
jenny

让Python从列表names中取出每一个名字,将其存储在遍历name中,并打印出来。

1. 深入地研究循环

循环是让计算机自动完成重复工具的常见方式之一,列表中的每个元素,都将执行循环体中的指定步骤

  • 这一步让Python读取列表names中的值,是控制循环次数的行 ,从第一个元素开始取值,每取值一次就进行一次循环,直到最后一个元素,
for name in names:
name = name[0]  第一次循环
-->name = name[1]  第二次循环
-->name = name[2]  第三次循环
-->...
-->name = name[-1]  最后一次循环
  • 这一步是循环体中的打印元素命令,每循环一次,都打印一次name元素
print(name)
  • 存储列表中的每个字的临时变量,可用指定任何名称,如:
for cat in cats:
for dog in dags:
for item in items:

2. 在for循环中执行跟多的操作
打印元素,打印字符串,添加制表符,换行符等

names = ['tom','john','mary','jenny']
for name in names:
    print("I will say hello to "+name+" now")
    print("\t\'Hello:\t"+name+".\'\n")
print("I have already greeted everyone.")
运行结果:
I will say hello to tom now
        'Hello: tom.'

I will say hello to john now
        'Hello: john.'

I will say hello to mary now
        'Hello: mary.'

I will say hello to jenny now
        'Hello: jenny.'

I have already greeted everyone.

二、避免缩进错误

Python根据缩进来判断代码行与前一个代码行的关系。for循环中,循环体中所有的操作都需要缩进,没有缩进的代码表示不在该循环体内。

1. 忘记缩进,提示缩进错误

names = ['tom','john','mary','jenny']
for name in names:
print("I will say hello to "+name+" now")
print("\t\'Hello:\t"+name+".\'\n")
print("I have already greeted everyone.")
运行结果:
IndentationError: expected an indented block

2. 非语法上的缩进问题,为逻辑错误,不提示错误

  • 忘记缩进额外的代码行,不提示错误
    如下所示,忘记缩进第二个输出语句,所以该输出语句不在循环体中,Python代码是合法的,可以运行程序,但运行结果不是预期的,这是逻辑错误。
names = ['tom','john','mary']
for name in names:
    print("I will say hello to "+name+" now")
print("\t\'Hello:\t"+name+".\'\n")
print("I have already greeted everyone.")

运行结果
I will say hello to tom now
I will say hello to john now
I will say hello to mary now
        'Hello: mary.'

I have already greeted everyone.
  • 缩进多余的代码行,为逻辑错误,不提示错误
    如下所示,第三个输出语句不应该缩进,但此时缩进了,表示该语句在循环体中,Python代码是合法的,可以运行程序。
names = ['tom','john','mary']
for name in names:
    print("I will say hello to "+name+" now")
    print("\t\'Hello:\t"+name+".\'\n")
    print("I have already greeted everyone.")
    
运行结果:
I will say hello to tom now
        'Hello: tom.'

I have already greeted everyone.
I will say hello to john now
        'Hello: john.'

I have already greeted everyone.
I will say hello to mary now
        'Hello: mary.'

I have already greeted everyone.

3. 不必要的缩进,提示缩进错误

message = "hello python"
    print(message)
    
运行结果:
IndentationError: unexpected indent

4. 遗漏冒号,提示语法错误
for语句末尾的冒号告诉Python,下一行是循环的第一行

names = ['tom','john','mary']
for name in names
    print("I will say hello to "+name+" now")
    print("\t\'Hello:\t"+name+".\'\n")
print("I have already greeted everyone.")

运行结果:
SyntaxError: invalid syntax

三、 创建数字列表

数据可视化中,处理的几乎都是有数字组成的几乎,如温度,距离,人口数量,经度,维度。列表非常适用于存储数字集合,Python提供了很多工具,可以高效处理数字列表。

1. 使用函数range()
Python函数range(),可以生成一系列数字

for value in range(1,5):
    print(value)
    
运行结果:
1
2
3
4
range(start: int, stop: int, step: int=...)

函数range()让Python从你指定的第一个值开始数,并在达到你指定的第二个值后停止,因此输出不包含第二个值。
第三个值表示指定的步长。

2. 使用函数range()创建数字列表
要创建数字列表,可使用函数list()将range()的结果直接转换为列表。

  • 简单数字列表
numbers = list(range(1,6))
print(numbers)

运行结果:
[1, 2, 3, 4, 5]
  • 指定步长
    数字列表从2开始,不断加2,直到达到或超过终值11
numbers = list(range(2,11,2))
print(numbers)

运行结果:
[2, 4, 6, 8, 10]
  • 创建平方数
    使用函数range()几乎可以创建任何需要的数字集,如创建乘方数字集,两个星号(**)表示乘方运算
numbers = []
for number in range(1,11):
    numbers.append(number**2)
print(numbers)

运行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

3. 对数字列表执行简单的统计计算
有几个专门处理数字列表的Python函数,如最大值max(),最小值min(),求和sum()

numbers = list(range(1,11))
print(max(numbers))
print(min(numbers))
print(sum(numbers))

运行结果:
10
1
55

4. 列表解析
列表解析将for循环和创建新元素的代码合并成一行,并自动附加新元素。

squares = [value**2 for value in range(1,11)]
print(squares)

运行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

首先指定一个空列表,squares = []
然后在中括号中添加表达式,用于生成你要存储的列表中的值,value**2
接下来编写一个for循环,用于给表达式提供值,for value in range(1,11)

四、使用列表的一部分

接下来,学习处理列表的部分元素——Python称之为切片
1. 切片
要创造切片,可指定要使用的第一个元素和最后一个元素的索引,与函数range()一样,Python在达到你指定的第二个索引前面的元素后停止。返回切片的值

name[起始索引:终止索引]
  • 起始索引
    自然数,表示切片从该自然数开始,正序提取元素
    负数,表示切片从该负数开始,正序提取元素
    没有指定,Python将自动从列表头开始提取元素
alphabet = ['a','b','c','d','e','g','h','i','j','k']
print(alphabet[3:5])
print(alphabet[-3:-1])
print(alphabet[:3])

运行结果:
['d', 'e']
['i', 'j']
['a', 'b', 'c']
  • 终止索引
    自然数,表示切片在该自然数结束,正序提取元素
    负数,表示切片在该负数结束,正序提取元素
    没有指定,Python将默认让切片终止于列表末尾
alphabet = ['a','b','c','d','e','g','h','i','j','k']
print(alphabet[3:5])
print(alphabet[3:-2])
print(alphabet[3:])
运行结果:
['d', 'e']
['d', 'e', 'g', 'h', 'i']
['d', 'e', 'g', 'h', 'i', 'j', 'k']

PS: 终止索引的值,可以大于列表的长度。此时切片将终止于列表末尾

alphabet = ['a','b','c','d','e','g','h','i','j','k']
print(alphabet[7:30])
运行结果:
['i', 'j', 'k']

2. 遍历切片
如果要遍历列表的部分元素,可在for循环中使用切片

alphabet = ['a','b','c','d','e','g','h','i','j','k']
for i in alphabet[:3]:
    print(i)
运行结果:
a
b
c

3. 复制列表
复制列表,创建一个包含整个列表的切片。这里主要是讲浅拷贝

  • 复制时创建副本,如同时省略起始索引和终止索引([:]
    使用切片拷贝,创建原列表的表层副本,并保存在新的变量中。二者指向两个列表。
import copy
 
son = ['python', 'copy']
base = ['a', 'b', 'c', 'd', 'e', son]
bak1 = base[:]
#列表表层的值改变,副本的值不会跟着改变
base[0] = 'test'
print('-' * 15, '[:]拷贝,修改列表浅层的值', '-' * 15)
print('base: ', base)
print("bak1: ", bak1)
print("\n")

#列表深层的值改变,副本的值跟着改变
son[0] = 'java'
print('-' * 15, '[:]拷贝,修改列表深层的值', '-' * 15)
print('base: ', base)
print("bak1: ", bak1)

运行结果:
--------------- [:]拷贝,修改列表浅层的值 ---------------
base:  ['test', 'b', 'c', 'd', 'e', ['python', 'copy']]
bak1:  ['a', 'b', 'c', 'd', 'e', ['python', 'copy']]


--------------- [:]拷贝,修改列表深层的值 ---------------
base:  ['test', 'b', 'c', 'd', 'e', ['java', 'copy']]
bak1:  ['a', 'b', 'c', 'd', 'e', ['java', 'copy']]

创建副本的拷贝方式有四种:
(1)切片: bak1 = base[:]
(2)list工厂函数:bak2 = list(base)
(3)python list对象的copy方法:bak3 = base.copy()
(4)copy模块的copy方法:bak4 = copy.copy(base)

  • 复制时创建关联,如使用等于号(=
    使用等于号拷贝,没有创建列表的表层副本。让Python将新变量关联到原列表上,二者指向同一个列表。
import copy
 
son = ['python', 'copy']
base = ['a', 'b', 'c', 'd', 'e', son]
bak1 = base
#列表表层的值改变,bak1也跟着改变
base[0] = 'test'
print('-' * 20, '“=”浅拷贝', '-' * 20)
print('base: ', base)
print("bak1: ", bak1)
运行结果:
base:  ['test', 'b', 'c', 'd', 'e', ['python', 'copy']]
bak1:  ['test', 'b', 'c', 'd', 'e', ['python', 'copy']]

五、深拷贝和浅拷贝

Python中对于对象的拷贝分为浅拷贝和深拷贝(函数:copy.deepcopy())两种方式。

1. Python数据类型分为值类型和引用类型
基本数据类型/值类型:对象本身不允许修改,数值的修改实际上是让变量指向一个新的对象(包含字符串、元组、数值)
引用数据类型/引用类型:对象本身允许修改(包含列表、字典)

(1)基本数据类型
基本数据类型保存在栈内存中,形式如下:栈内存中分别存储变量的标识符以及变量的值。
在这里插入图片描述
字符串a = "A"在栈内存中时这样的:
在这里插入图片描述

(2)引用数据类型
引用数据类型保存在堆内存中,栈内存存储的变量的标识符以及对象在堆内存中的存储地址,当需要访问引用数据类型的值是,首先从栈中获得该对象的地址指针,然后再从对应的堆内存中获取所需的数据。
在这里插入图片描述
字典a = {name:"jack"}在内存中是这样的:
在这里插入图片描述

2. 基本数据类型和引用数据类型的拷贝
浅拷贝:仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响。
深拷贝:复制实例,在堆中重新分配内存,拥有不同的地址,但值是一样的,复制之后的对象与原来的对象完全隔离,互不影响。

深浅拷贝的主要区别就是:复制的是引用(地址)还是复制的是实例。

基本数据类型的浅拷贝和深拷贝效果一样?

(3)基本数据类型的浅拷贝
这里的浅拷贝使用 “=” 号

a = 1
b = a
a = 2
print("a = "+str(a))
print("b = "+str(b))
运行结果:
a = 2
b = 1

改变 a 变量的值,并不会影响 b 的值。
内存中是这样的:

a = 1

在这里插入图片描述

b = a

在这里插入图片描述

a = 2

在这里插入图片描述
(4)引用数据类型的浅拷贝:当你在复制引用类型的时候,实际上只是复制了指向堆内存的地址,即原来的变量与复制的新变量指向了同一个东西。
这里的浅拷贝使用 “=” 号

a =  {"name":"jack","age":20}
b = a
a["age"] = 23

print("a = " + str(a))
print("b = " + str(b))
运行结果:
a = {'name': 'jack', 'age': 23}
b = {'name': 'jack', 'age': 23}

改变 a 变量的值,会影响 b 的值。
内存中是这样的:

a =  {"name":"jack","age":20}

在这里插入图片描述

b = a

在这里插入图片描述

a["age"] = 23

在这里插入图片描述

(5)引用数据类型的深拷贝
Python的深拷贝使用copy.deepcopy()

import copy
a =  {"name":"jack","age":20}
b = copy.deepcopy(a)
a["age"] = 23

print("a = " + str(a))
print("b = " + str(b))

运行结果:
a = {'name': 'jack', 'age': 23}
b = {'name': 'jack', 'age': 20}

让b在内存中像下图这样,就是深拷贝。
在这里插入图片描述
实现过程:利用 递归 来实现深复制,对属性中所有引用类型的值,遍历到是基本类型的值为止。

六、元组

Python将不能修改的值称为不可变的,而不可变的列表被称为元组。
1. 定义元组
元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其元素,就像访问列表元素一样。
元组中的元素不能修改,如果试图修改则会报错

alphabets = ('a','b','c','d','e')
alphabets[2] = 'test'
运行结果:
TypeError: 'tuple' object does not support item assignment

2. 遍历元组中的所有值
像列表一样,使用用for循环遍历

alphabets = ('a','b','c','d','e')
for alphabet in alphabets:
    print(alphabet)
运行结果:
a
b
c
d
e
  1. 修改元组变量
    虽然不能修改元组的元素,但是可以给存储元组的变量赋值
alphabets = ('a','b','c','d','e')
print(alphabets)
alphabets = ('test1','test2','c','d','e')
print(alphabets)

运行结果:
('a', 'b', 'c', 'd', 'e')
('test1', 'test2', 'c', 'd', 'e')

相比于列表,元组是更简单的数据结果。如果需要存储的一组值在程序中的整个生命周期内都不可变,可使用元组。

七、设置代码格式

  1. 格式设置指南
    PEP8是最古老的PEP之一,它向Python程序员提供了代码格式设置指南
  2. 缩进
    PEP8建议每级缩进都使用四个空格,既可以提高可读性,又留下了足够的多级缩进空间。一般不用制表符缩进,因为不同软件制表符的长度不一样。
  3. 行长
    很多Python程序员都建议每行不超过80个字符,PEP8还建议注释的行长都不超过72个字符。
    PEP8中有关行长的指南,有一条可逾越的红线,这是一个视觉标志,让你知道不能越过的界限在什么地方。
  4. 空行
    要将程序的不同部分分开,可使用空行。不建议滥用,影响可读性。

还有其他格式的指南,以后再学习。

八、小结、补充

今天学习了如何高效处理列表中的元素,使用for循环遍历列表,Python如何根据缩进来确定程序的结构以及如何避免一些常见的缩进错误,创建简单的数字列表,复制列表,元组,代码格式。

缩进错误:IndentationError: unexpected indent

数值:
int(符号整数):通常被称为是整数或整数,没有小数点的正或负整数。
long(长整数):无限大小的整数,这样写整数和一个大写或小写的L。
float(浮点实际值):小数除以整数部分和小数部分的书面。
complex (复数):a+bi, a是真正的数字部分,b是虚部。复数不使用Python编程。

深拷贝,浅拷贝
https://www.cnblogs.com/echolun/p/7889848.html
https://zhuanlan.zhihu.com/p/26282765

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值