序列
序列是一种数据存储方式,用来存储一系列的数据。在内存中,序列就是一块用来存放 多个值的连续的内存空间。
python 中常用的序列结构有: 字符串、列表、元组、字典、集合
列表
用于存储任意数目、任意类型的数据集合。列表是内置可变序列.
标准语法格式: a = [10,20,'abc',True]
列表的创建
基本语法[]创建,list()可以将任何可迭代的数据转化成列表
>>> a = [10,20,'gaoqi','sxt']
>>> a
[10, 20, 'gaoqi', 'sxt']
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = list("gaoqi,sxt")
>>> a
['g', 'a', 'o', 'q', 'i', ',', 's', 'x', 't']
range()创建整数列表
range()返回的是一个 range 对象,而不是列表。
range([start,] end [,step])
- start 参数:可选,表示起始数字。默认是 0 end
- 参数:必选,表示结尾数字。 step
- 参数:可选,表示步长,默认为 1
>>> list(range(3,15,2))
[3, 5, 7, 9, 11, 13]
>>> list(range(15,3,-2))
[15, 13, 11, 9, 7, 5]
>>> list(range(3,-10,-1))
[3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
推导式生成列表
>>> a = [x*2 for x in range(5)if x%2==0]
>>> a
[0, 4, 8]
>>> a = [x*2 for x in range(5)if x%2==0]
>>> a
[0, 4, 8]
常用方法
列表中的元素可以各不相同,可以是任意类型。Python 的列表大小可变,根据需要随时增加或缩小
| 方法 | 要点 | 描述 |
|---|---|---|
| list.append(x) | 增加元素 | 将元素 x 增加到列表 list 尾部 |
| list.extend(aList) | 增加元素 | 将列表 alist 所有元素加到列表 list 尾部 |
| list.insert(index,x) | 增加元素 | 在列表 list 指定位置 index 处插入元素 x |
| list.remove(x) | 删除元素 | 在列表 list 中删除首次出现的指定元素 x |
| list.pop([index]) | 删除元素 | 删除并返回列表 list 指定为止 index 处的元素,默认是 最后一个元素 |
| list.clear() | 删除所有元素 | 删除列表所有元素,并不是删除列表对象 |
| list.index(x) | 访问元素 | 返回第一个 x 的索引位置,若不存在 x 元素抛出异常 |
| list.count(x) | 计数 | 返回指定元素 x 在列表 list 中出现的次数 |
| len(list) | 列表长度 | 返回列表中包含元素的个数 |
| list.reverse() | 翻转列表 | 所有元素原地翻转 |
| list.sort() | 排序 | 所有元素原地排序 |
| list.copy() | 浅拷贝 | 返回列表对象的浅拷贝 |
切片操作
[起始偏移量 start:终止偏移量 end[:步长 step]]
注:当步长省略时顺便可以省略第二个冒号
| 操作和说明 | 示例 | 结果 |
|---|---|---|
| [:] 提取整个列表 | [10,20,30][:] | [10,20,30] |
| [:end]从头开始知道 end-1 | [10,20,30][:2] | [10,20] |
| [start:end]从 start 到 end-1 | [10,20,30,40][1:3] | [20,30] |
| [start:end:step] 从 start 提 取到 end-1,步长是 step | [10,20,30,40,50,60,70][1:6: 2] | [20, 40, 60] |
其他操作(三个量为负数)的情况:
| 示例 | 说明 | 结果 |
|---|---|---|
| [10,20,30,40,50,60,70][-3:] | 倒数三个 | [50,60,70] |
| 10,20,30,40,50,60,70][-5:-3] | 倒数第五个到倒数 第三个(包头不包尾) | [30,40] |
| [10,20,30,40,50,60,70][::-1] | 步长为负,从右到左 反向提取 | [70, 60, 50, 40, 30, 20, 10] |
列表遍历
for obj in listObj:
print(obj)
列表排序
- sort()升序
- sort(reverse=True) 降序
- random.shuffle(a) 乱序
>>> a = [20,10,30,15,40]
>>> a.sort()
>>> a
[10, 15, 20, 30, 40]
>>> a = [20,10,30,15,40]
>>> a.sort(reverse=True)
>>> a
[40, 30, 20, 15, 10]
>>> a = [20,10,30,15,40]
>>> import random
>>> random.shuffle(a)
>>> a
[15, 30, 40, 10, 20]
sorted()进行排序,这个方法返回新列表,不对原列表做修改。
>>> a = [20,10,30,40]
>>> sorted(a)
[10, 20, 30, 40]
>>> a
[20, 10, 30, 40]
>>> sorted(a,reverse=True)
[40, 30, 20, 10]
>>> a
[20, 10, 30, 40]
reversed()返回迭代器
>>> a = [20,10,30,40]
>>> c = reversed(a)
>>> c
<list_reverseiterator object at 0x00000214ABD6E198>
>>> list(c)
[40, 30, 10, 20]
>>> list(c)
[]
迭代对象 在第一次时已经遍历结束了,第二次不能再使用。
其他内置函数
>>> a = [3,10,20,15,9]
>>> max(a)
20
>>> min(a)
3
>>> sum(a)
57
二维列表
>>> a = [ ["高小一",18,30000,"北京"], ["高小二",19,20000,"上海"], ["高小一",20,10000,"深圳"], ]
>>> for m in range(3):
... for n in range(4):
... print(a[m][n],end='\t')
... print()
...
高小一 18 30000 北京
高小二 19 20000 上海
高小一 20 10000 深圳
元组 tuple
元组属于不可变序列,不能修改元组中的 元素。 支持如 下操作:
- 索引访问
- 切片操作
- 连接操作
- 成员关系操作
- 比较运算操作
- 计数:元组长度 len()、最大值 max()、最小值 min()、求和 sum()等
元组的创建
- 通过()创建元组。小括号可以省略。
- 通过 tuple()创建元组
>>> a = (10,20,30)
>>> a
(10, 20, 30)
>>> b = 10,20,30
>>> b
(10, 20, 30)
>>> b = tuple("abc")
>>> b
('a', 'b', 'c')
>>> b = tuple(range(3))
>>> b
(0, 1, 2)
>>> b = tuple([2,3,4])
>>> b
(2, 3, 4)
>>> a
(10, 20, 30)
# 元组的元素不能修改
>>> a[3]=33
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
# 元组访问和列表一样,返回的仍然是元组对象
>>> a = (20,10,30,9,8)
>>> a[1:3]
(10, 30)
>>> a[1]
10
排序
使用内置函数 sorted(tupleObj),并生成新的列表对象
>>> a = (20,10,30,9,8)
>>> sorted(a)
[8, 9, 10, 20, 30]
zip
zip(列表 1,列表 2,...)将多个列表对应位置的元素组合成为元组,并返回这个 zip 对象。
[8, 9, 10, 20, 30]
>>> a = [10,20,30]
>>> b = [40,50,60]
>>> c = [70,80,90]
>>> d = zip(a,b,c)
>>> d
<zip object at 0x0000023468E9B788>
>>> list(d)
[(10, 40, 70), (20, 50, 80), (30, 60, 90)]
字典
字典是“键值对”的无序可变序列,“键”是任意的不可变数据,比如:整数、浮点数、字符串、元组。但是:列表、 字典、集合这些可变对象,不能作为“键”。并且“键”不可重复,“值”可以是任意的数据,并且可重复。
字典创建
>>> a = {'name':'gaoqi','age':18,'job':'programmer'}
>>> b = dict(name='gaoqi',age=18,job='programmer')
>>> c = dict([("name","gaoqi"),("age",18)])
#zip创建
>>> k = ['name','age','job']
>>> v = ['gaoqi',18,'techer']
>>> d = dict(zip(k,v))
>>> d
{'name': 'gaoqi', 'age': 18, 'job': 'techer'}
#fromkeys 创建值为空的字典
>>> a = dict.fromkeys(['name','age','job'])
>>> a
{'name': None, 'age': None, 'job': None}
字典元素的访问
- 通过 [] 获得“值”。
>>> a = {'name':'gaoqi','age':18,'job':'programmer'}
>>> a['name']
'gaoqi'
>>> a['nam'] #键不存在,则抛出异常。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'nam'
- 通过 get()方法获得“值”。
>>> a.get('name')
'gaoqi'
>>> a.get('nam') #键不存在,返回 None
>>>
>>> a.get('nam','没这个键') #也可以设 定指定键不存在时的默认返回
'没这个键'
- 列出所有键值对
>>> a.items()
dict_items([('name', 'gaoqi'), ('age', 18), ('job', 'programmer')])
- 列出所有键、值
>>> a.keys()
dict_keys(['name', 'age', 'job'])
>>> a.values()
dict_values(['gaoqi', 18, 'programmer'])
- 其他
>>> len(a)
3
>>> 'name' in a
True
>>> 'nam' in a
False
元素添加、修改、删除
- 若“键”已存在,则覆盖;“键”不存在, 则新增。
>>>a = {'name':'gaoqi','age':18,'job':'programmer'}
>>> a['address']='西三旗 1 号院'
>>> a['age']=16
>>> a
{'name': 'gaoqi', 'age': 16, 'job': 'programmer', 'address': '西三旗 1 号院'}
- update()将新字典中所有键值对全部添加到旧字典上。若key 有重复,则覆盖。
>>> a = {'name':'gaoqi','age':18,'job':'programmer'}
>>> b = {'name':'gaoxixi','money':1000,'sex':'男的'}
>>> a.update(b)
>>> a
{'name': 'gaoxixi', 'age': 18, 'job': 'programmer', 'money': 1000, 'sex': '男的'}
- 删除: del()方法,clear()删除所有键值对;pop()删除指定`键值对; popitem()随机删除和返回该键值对。
>>> a = {'name':'gaoqi','age':18,'job':'programmer'}
>>> del(a['name'])
>>>
a {'age': 18, 'job': 'programmer'}
>>> b = a.pop('age')
>>> b
18
>>> a = {'name':'gaoqi','age':18,'job':'programmer'}
>>> a.popitem() ('job', 'programmer')
>>> a
{'name': 'gaoqi', 'age': 18}
>>> a.popitem() ('age', 18)
>>> a
{'name': 'gaoqi'}
序列解包
>>> x,y,z=(20,30,10)
>>> x
20
>>> y
30
>>> z
10
>>> (a,b,c)=(9,8,10)
>>> a
9
>>> [a,b,c]=[10,20,30]
>>> a
10
序列解包用于字典时,默认对“键”; 如果需要对键值对操作,则需要使用 items();如果需要对“值”进行操作,则需要使用 values();
>>> s = {'name':'gaoqi','age':18,'job':'teacher'}
>>> name,age,job=s #默认对键进行操作
>>> name
name'
>>> name,age,job=s.items() #对键值对进行操作
>>> name
('name', 'gaoqi')
>>> name,age,job=s.values() #对值进行操作
>>> name
'gaoqi'
字典核心底层
- 字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的 每个单元叫做 bucket。
- 每个 bucket 有两部分:一个是键对象的引用,一个是值对象的引用
。。。。待补充
集合
集合是无序可变,元素不能重复。
创建和删除
- add()
>>> a={3,5,7}
>>> a.add(9)
>>> a
{9, 3, 5, 7}
- set(),将列表、元组等可迭代对象转成集合。
>>> a = ['a','b','c','b']
>>> b = set(a)
>>> b
{'b', 'a', 'c'}
- . remove()删除指定元素;clear()清空整个集合
>>> a = {10,20,30,40,50}
>>> a.remove(20)
>>> a
{10, 50, 30}
并集、交集、差集
>>> a = {1,3,'sxt'}
>>> b = {'he','it','sxt'}
>>> a|b #并集
{1, 3, 'sxt', 'he', 'it'}
>>> a&b #交集
{'sxt'}
>>> a-b #差集
{1, 3}
>>> a.union(b) #并集
{1, 3, 'sxt', 'he', 'it'}
>>> a.intersection(b) #交集
{'sxt'}
>>> a.difference(b) #差集
{1, 3}
控制语句
分支结构
单分支结构
if 语句单分支结构的语法形式如下:
if 条件表达式:
语句/语句块
- 条件表达式:可以是逻辑表达式、关系表达式、算术表达式等等。
- 语句/语句块:可以是一条语句,也可以是多条语句。
num = input("输入一个数字:")
if int(num)<10:
print(num)
条件表达式的值为 False 的情况如下:
- False、0、0.0、空值 None、空序列对象(空列表、空元祖、空集合、空字典、空字符串)、空 range 对象、空迭代对象。
>>> if 3: #整数作为条件表达式
... print("ok")
...
ok
>>> if a:
... print("空列表,False")
...
>>>
条件表达式中,不能有赋值操作符“=”
双分支
双分支结构的语法格式如下:
if 条件表达式 :
语句 1/语句块 1
else:
语句 2/语句块 2
【操作】输入一个数字,小于 10,则打印该数字;大于 10,则打印“数字太大”
num = input("输入一个数字:")
if int(num)<10:
print(num)
else:
print("数字太大")
三元条件运算符
三元条件运算符语法格式如 下:
条件为真时的值 if (条件表达式) else 条件为假时的值
num = input("请输入一个数字")
print( num if int(num)<10 else "数字太大")
多分支
多分支选择结构的语法格式如下:
if 条件表达式 1 :
语句 1/语句块 1
elif 条件表达式 2:
语句 2/语句块 2
...
elif 条件表达式 n :
语句 n/语句块 n
[else:
语句 n+1/语句块 n+1
]
【操作】输入一个学生的成绩,将其转化成简单描述:不及格(小于 60)、及格(60-79)、良 好(80-89)、优秀(90-100)。
score = int(input("请输入分数"))
grade = ''
if score<60 :
grade = "不及格"
elif score<80 :
grade = "及格"
elif score<90 :
grade = "良好"
elif score<=100:
grade = "优秀"
print("分数是{0},等级是{1}".format(score,grade))
嵌套
选择结构可以嵌套,注意控制好不同级别代码块的缩进量,因为缩进量决定了代码的从属关系。
【操作】输入一个分数。分数在 0-100 之间。90 以上是 A,80 以上是 B,70 以上是 C,60 以上是 D。60 以下是 E。
score = int(input("请输入一个在 0-100 之间的数字:"))
grade = ""
if score>100 or score<0:
score = int(input("输入错误!请重新输入一个在 0-100 之间的数字:"))
else:
if score>=90:
grade = "A"
elif score>=80:
grade = 'B'
elif score>=70:
grade = 'C'
elif score>=60:
grade = 'D'
else:
grade = 'E'
print("分数为{0},等级为{1}".format(score,grade))
程序优化:
score = int(input("请输入一个在 0-100 之间的数字:"))
degree = "ABCDE"
num = 0
if score>100 or score<0:
score = int(input("输入错误!请重新输入一个在 0-100 之间的数字:"))
else:
num = score//10
if num<6:
num=5
print("分数是{0},等级是{1}".format(score,degree[9-num]))
循环结构
表达这样的逻辑:如果符合条件,则反 复执行循环体里的语句。在每次执行完后都会判断一次条件是否为 True,如果 为 True 则重复执行循环体里的语句。循环体里面的语句至少应该包含改变条件表达式的语句,以使循环趋于结束;否 则,就会变成一个死循环。
while 循环
while 循环的语法格式如下:
while 条件表达式:
循环体语句
【操作】利用 while 循环打印从 0-10 的数字。
num = 0 while num<=10:
print(num)
num += 1
for 循环和可迭代对象遍历
for 循环通常用于可迭代对象的遍历。for 循环的语法格式如下:
for 变量 in 可迭代对象:
循环体语句
【操作】遍历一个元组或列表
for x in (20,30,40):
print(x*3)
Python 包含以下几种可迭代对象:
- 序列。包含:字符串、列表、元组
- 字典
- 迭代器对象(iterator)
- 生成器函数(generator)
- 文件对象 【操作】遍历字典
d = {'name':'gaoqi','age':18,'address':'西三旗 001 号楼'}
for x in d: #遍历字典所有的 key
print(x)
for x in d.keys():#遍历字典所有的 key
print(x)
for x in d.values():#遍历字典所有的 value
print(x)
for x in d.items():#遍历字典所有的"键值对"
print(x)
结果:
name
age
address
name
age
address
gaoqi
18
西三旗 001 号楼
('name', 'gaoqi')
('age', 18)
('address', '西三旗 001 号楼')
range 对象是一个迭代器对象,用来产生指定范围的数字序列。格式为:
range(start, end [,step]) 生成的数值序列从 start 开始到 end 结束(不包含 end)。若没有填写 start,则默认从 0 开始。step 是可选的步长,默认为 1。
for i in range(10) #产生序列:0 1 2 3 4 5 6 7 8 9
for i in range(3,10) #产生序列:3 4 5 6 7 8 9
for i in range(3,10,2) #产生序列:3 5 7 9
【操作】利用 for 循环,计算 1-100 之间数字的累加和;计算 1-100 之间偶数的累加和, 计算 1-100 之间奇数的累加和。
sum_all = 0 #1-100 所有数的累加和
sum_even = 0 #1-100 偶数的累加和
sum_odd = 0 #1-100 奇数的累加和
for num in range(101):
sum_all += num
if num%2==0:sum_even += num
else:sum_odd += num
print("1-100 累加总和{0},奇数和{1},偶数和{2}".format(sum_all,sum_odd,sum_even))
执行结果:
======================== RESTART: F:/Programs/test.py ========================
1-100 累加总和5050,奇数和2500,偶数和2550
【操作】利用嵌套循环打印九九乘法表
for m in range(1,10):
for n in range(1,m+1):
print("{0}*{1}={2}".format(m,n,(m*n)),end="\t")
print()
执行结果:
======================== RESTART: F:/Programs/test.py ========================
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
break 语句
break 语句可用于 while 和 for 循环,用来结束整个循环。当有嵌套循环时,跳出最近一层的循环。
【操作】使用 break 语句结束循环
while True:
a = input("请输入一个字符(输入 Q 或 q 结束)")
if a.upper()=='Q':
print("循环结束,退出")
break
else:print(a)
continue 语句
continue 语句用于结束本次循环,继续下一次。
【操作】要求输入员工的薪资,若薪资小于 0 则重新输入。最后打印出录入员工的数量和 薪资明细,以及平均薪资。
empNum = 0
salarySum= 0
salarys = []
while True:
s = input("请输入员工的薪资(按 Q 或 q 结束)")
if s.upper()=='Q':
print("录入完成,退出")
break
if float(s)<0:
continue
empNum +=1
salarys.append(float(s))
salarySum += float(s)
print("员工数{0}".format(empNum))
print("录入薪资:",salarys)
print("平均薪资{0}".format(salarySum/empNum))
执行结果
======================== RESTART: F:\Programs\test.py ========================
请输入员工的薪资(按 Q 或 q 结束)2000
请输入员工的薪资(按 Q 或 q 结束)3000
请输入员工的薪资(按 Q 或 q 结束)q
录入完成,退出
员工数2
录入薪资: [2000.0, 3000.0]
平均薪资2500.0
while、for 的 else 语句
while、for 循环可以附带一个 else 语句(可选)。如果 for、while 语句没有被 break 语句 结束,则会执行 else 子句,否则不执行。
while 条件表达式:
循环体
else:
语句块
或者:
for 变量 in 可迭代对象:
循环体
else:
语句块
循环代码优化
- 尽量减少循环内部不必要的计算
- 嵌套循环中,尽量减少内层循环的计算,尽可能向外提。
- 局部变量查询较快,尽量使用局部变量
- 连接多个字符串,使用 join()而不使用+
- 列表进行元素插入和删除,尽量在列表尾部操作
# 循环代码优化测试
import time
start = time.time()
for i in range(1000):
result = []
for m in range(10000):
result.append(i * 1000 + m * 100)
end = time.time()
print("耗时:{0}".format((end - start)))
start2 = time.time()
for i in range(1000):
result = []
c = i * 1000
for m in range(10000):
result.append(c + m * 100)
end2 = time.time()
print("耗时:{0}".format((end2 - start2)))
执行结果:
======================== RESTART: F:\Programs\test.py ========================
耗时:2.0914063453674316
耗时:1.5199341773986816
zip()并行迭代
通过 zip()函数对多个序列进行并行迭代,zip()函数在最短序列“用完”时就会停.
names = ("高淇","高老二","高老三","高老四")
ages = (18,16,20,25)
jobs = ("老师","程序员","公务员")
for name,age,job in zip(names,ages,jobs):
print("{0}--{1}--{2}".format(name,age,job))
result:
======================== RESTART: F:\Programs\test.py ========================
高淇--18--老师
高老二--16--程序员
高老三--20--公务员
推导式
- 列表推导式生成列表对象:
[表达式 for item in 可迭代对象 ]或者:{表达式 for item in 可迭代对象 if 条件判断} - 字典的推导式生成字典对象:
{key_expression : value_expression for 表达式 in 可迭代对象} - 集合推导式生成集:
{表达式 for item in 可迭代对象 }或者:{表达式 for item in 可迭代对象 if 条件判断}
#列表
>>> [x for x in range(1,5)]
[1, 2, 3, 4]
>>> [x*2 for x in range(1,20) if x%5==0 ]
[10, 20, 30]
>>> cells = [(row,col) for row in range(1,5) for col in range(1,4)]
>>> cells
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3), (4, 1), (4, 2), (4, 3)]
#字典
>>> my_text ='to do or not to do'
>>> char_count = {c:my_text.count(c) for c in my_text}
>>> char_count
{'t': 3, 'o': 6, ' ': 5, 'd': 2, 'r': 1, 'n': 1}
#集合
>>> {x for x in range(1,100) if x%9==0}
{99, 36, 72, 9, 45, 81, 18, 54, 90, 27, 63}
- 生成器推导式(生成元组)
>>> (x for x in range(1,100) if x%9==0)
<generator object <genexpr> at 0x000001EA5E3496D8>
元组是没有推导式的。一个生成器只能运行一次。第一次迭代可以得到数据,再次迭代就没有了
>>> gnt = (x for x in range(1,100) if x%9==0)
>>> for x in gnt:
print(x,end=' ')
9 18 27 36 45 54 63 72 81 90 99
>>> for x in gnt:
print(x,end=' ')
>>>