python学习笔记(二)序列结构&控制语句

285 阅读19分钟

序列

序列是一种数据存储方式,用来存储一系列的数据。在内存中,序列就是一块用来存放 多个值的连续的内存空间。

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

元组属于不可变序列,不能修改元组中的 元素。 支持如 下操作:

  1. 索引访问
  2. 切片操作
  3. 连接操作
  4. 成员关系操作
  5. 比较运算操作
  6. 计数:元组长度 len()、最大值 max()、最小值 min()、求和 sum()等

元组的创建

  1. 通过()创建元组。小括号可以省略。
  2. 通过 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}

字典元素的访问

  1. 通过 [] 获得“值”。
>>> 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'
  1. 通过 get()方法获得“值”。
>>> a.get('name')
'gaoqi'
>>> a.get('nam')  #键不存在,返回 None
>>>
>>> a.get('nam','没这个键')  #也可以设 定指定键不存在时的默认返回
'没这个键'
  1. 列出所有键值对
>>> a.items()
dict_items([('name', 'gaoqi'), ('age', 18), ('job', 'programmer')])
  1. 列出所有键、值
>>> a.keys()
dict_keys(['name', 'age', 'job'])
>>> a.values()
dict_values(['gaoqi', 18, 'programmer'])
  1. 其他
>>> len(a)
3
>>> 'name' in a
True
>>> 'nam' in a
False

元素添加、修改、删除

  1. 若“键”已存在,则覆盖;“键”不存在, 则新增。
>>>a = {'name':'gaoqi','age':18,'job':'programmer'} 
>>> a['address']='西三旗 1 号院' 
>>> a['age']=16 
>>> a 
{'name': 'gaoqi', 'age': 16, 'job': 'programmer', 'address': '西三旗 1 号院'}
  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': '男的'}
  1. 删除: 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 有两部分:一个是键对象的引用,一个是值对象的引用

。。。。待补充

集合

集合是无序可变,元素不能重复。

创建和删除

  1. add()
>>> a={3,5,7}
>>> a.add(9)
>>> a
{9, 3, 5, 7}
  1. set(),将列表、元组等可迭代对象转成集合。
>>> a = ['a','b','c','b'] 
>>> b = set(a) 
>>> b 
{'b', 'a', 'c'}
  1. . 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 条件表达式: 
   语句/语句块
  1. 条件表达式:可以是逻辑表达式、关系表达式、算术表达式等等。
  2. 语句/语句块:可以是一条语句,也可以是多条语句。
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 包含以下几种可迭代对象:

  1. 序列。包含:字符串、列表、元组
  2. 字典
  3. 迭代器对象(iterator)
  4. 生成器函数(generator)
  5. 文件对象 【操作】遍历字典
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:
    语句块

循环代码优化

  1. 尽量减少循环内部不必要的计算
  2. 嵌套循环中,尽量减少内层循环的计算,尽可能向外提。
  3. 局部变量查询较快,尽量使用局部变量
  4. 连接多个字符串,使用 join()而不使用+
  5. 列表进行元素插入和删除,尽量在列表尾部操作
# 循环代码优化测试
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=' ')

>>>