从零开始学python 6(持续更新中ing)
从零开始学python5(持续更新中ing)
承接上文
1.8 列表的其他操作
函数 | 功能描述 |
len | 获取列表中元素的个数 |
reverse | 反转列表中的元素 |
sort | 对列表元素进行排序 |
copy | 对列表进行拷贝 |
# sort()--独属于列表的排序方法,默认升序排序,降序还是使用此函数
当数字作为条件的时候,只有两种情况:
0和非0数字,0表示False,非0数字表示True
n = [33, 22, 25, 15, 11, 56, 52]
n.sort()
print(n)
降序:n.sort(reverse=True)
# sorted是python自带的一个独立的排序函数,它不需要被任何数据调用
# sorted只是引用某一个序列中的元素做了排序操作,产生一个排好序的新的列表
print(sorted(n))
# sort()和sorted()的区别
# 1、sort() 内置方法 依赖于对象 需要调用 无返回值 原列表改变
# 2、sorted() 内置函数 无需调用 有返回值 原列表不变
l1 = [1,2,3]
l2 = l1
import copy
l3 = copy.deepcopy(l1)
# l2是引用,和l1的内存地址一样,也就是l1和l2指向同一片内存地址
# l3是深拷贝,生成副本,是一个新对象,l1和l3内存地址不一样
# 也就是说l1是源文件,l2就是快捷方式,l3是复制粘贴后的副本
print(id(l1), id(l2), id(l3))
l1 = [1, 2, 3, ['a', 'b', 'c']]
# 浅拷贝
l2 = l1.copy()
# 深拷贝
import copy
l3 = copy.deepcopy(l1)
print("修改前")
print(l1)
print(l2)
print(l3)
# 修改值
l1[0] = 66
l2[1] = 88
l3[2] = 99
print("修改值后")
print(l1)
print(l2)
print(l3)
# 修改可变对象
l1[3][0] = 'hqyj'
l2[3][1] = 'hello'
l3[3][2] = 'xxxx'
print("修改可变对象后")
print(l1)
print(l2)
print(l3)
# 深拷贝与浅拷贝的对比
# 深拷贝:将原列表直接复制一份,生成一个新对象[列表],和原列表的内存地址不一样,原列表修改,新列表不变
# 浅拷贝:将原列表的值复制一份,同时引用而不复制原列表的【可变对象】,原列表修改值,新列表值不变;原列表修改
# 可变对象,新列表可变对象也变
# 实际变成中,浅拷贝使用多,因为深拷贝完全复制一个新对象会存在资源浪费。
1.9 列表嵌套
在python中,我们是允许列表嵌套的,也就是一个列表中的所有元素都是列表。它的元素访问和一层列表略有区别,可能需要添加多个[]下标去访问。
menu = [['h红烧牛肉面', 18], ['x香辣牛肉面', 16], ['a安徽板面', 15], ['c重庆小面', 20]]
print(menu[0])
print(menu[1][1])
menu.append(['t铁牛牛肉面', 88])
print(menu)
menu.sort()
print(menu)
import operator
menu.sort(key=operator.itemgetter(1))
print(menu)
1.10 列表推导式
语法格式:
列表名 = [表达式 for 循环]
练习题: 利用列表推导式方式生成: 1-10之间的奇数
L = [i for i in range(1,10,2)]
print(L)
生成10个随机数,范围在10-30之间
l1 = [i for i in range(10) if i%3==0]
print(l1)
字符串s1 ='ABC',字符串 s2 = '123',
要求:
生成序列 A1 A2 A3 B1 B2 B3 C1 C2 C3
s1 = 'ABC'
s2 = '123'
l3 = [i+j for i in s1 for j in s2]
print(l3)
过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
list1 = ['太白金星', 'fdsaf', 'alex', 'sb', 'ab']
list1 = ['太白金星', 'fdsaf', 'alex', 'sb', 'ab']
l4 = [i.upper() for i in list1 if len(i)>3]
print(l4)
课后练习题:
1. 定义列表是['a', 'b', 'b', 'a', 'c', 'a'], 删除相邻的重复项,最后留下['c', 'a']
L = ['a','b','b','a','c','a','b']
i = 0
while i < len(L)-1:
if L[i] == L[i-1]:
del L[i-1]
del L[i-1]
i -= 1
else:
i += 1
print(L)
2. 创建一个空列表,命名为 names, 往里面添加 Lihua、Rain、Jack、Xiuxiu、Peiqi 和 Black 元素 要求:
(1) 往 names 列表里 Black 前面插入一个 Blue
(2) 把 names 列表中 Xiuxiu 的名字改成中文。 往 names 列表中 Rain 后面插入一个子列表["oldboy","oldgirl"]。
2. 创建一个空列表,命名为 names,
往里面添加 Lihua、Rain、Jack、Xiuxiu、Peiqi 和 Black 元素
要求:
(1) 往 names 列表里 Black 前面插入一个 Blue
(2) 把 names 列表中 Xiuxiu 的名字改成中文。
往 names 列表中 Rain 后面插入一个子列表["oldboy","oldgirl"]。
3. 系统里面有多个用户,用户的信息目前保存在列表里面 users = ['root','westos'] passwd = ['123','456'] 用户登陆(判断用户登陆是否成功) 判断用户是否存在 如果存在判断用户密码是否正确 如果正确,登陆成功,退出循环 如果密码不正确,重新登陆,总共有三次机会登陆 如果用户不存在 重新登陆,总共有三次机会
users = ['root','westos']
passwds = ['123','456']
for i in range(3):
user = input("请输入用户名:")
if user in users:
passwd = input("请输入密码:")
if passwd == passwds[users.index(user)]:
print("登陆成功")
break
else:
print("密码错误")
else:
print("用户不存在")
else:
print("登陆失败")
4. 实现输出10行的杨辉三角形
l1 = []
for i in range(10):
l1.append([1])
for j in range(1,i):
l1[i].append(l1[i-1][j-1]+l1[i-1][j])
if i>0:
l1[i].append(1)
for i in l1:
print(i)
二、数据类型 -- 元组(tuple)
2.1 元组是什么?
元组和列表相似,只是列表元素放在 [] 里面,元组的元素放在 () 里面。
L = [1, 2, 3, 4, 5]
print(L, type(L))
T = (1, 2, 3, 4, 5)
print(T, type(T))
2.2 访问元组
元组的访问,和列表一样可以直接遍历元素,也可以通过索引/下标遍历。
2.2.1 遍历元组
t = (1, 2, 3, [6, 7, 8])
for i in t:
print(i)
for i in range(len(t)):
print(t[i])
2.2.2 元组截取/切片
t = (1, 2, 3, [6, 7, 8])
print(t[:])
print(t[::-1])
print(t[1:5:2])
2.3 修改元组【NO】
元组中的元素项是不允许修改的。
t = (1, 2, 3, [6, 7, 8])
t[3] = 'xxxx'
print(t)
# TypeError: 'tuple' object does not support item assignment
# 类型错误:tuple 对象不支持项赋值
元组可以包含可变对象——列表,对列表项进行修改。
t = (1, 2, 3, [6, 7, 8])
t[4][0] = 666
print(t)
# 元组对象不支持项赋值
# 但是元组可以包含可变对象——列表
# 然后对列表项进行赋值修改
2.4 删除元组【NO】
不可以删除元组元素,可以删除整个元素
t = (1, 2, 3, 'hqyj', [6, 7, 8])
# del t[0]
del t
2.5 元组的运算
因为元组是不可变的,所以元组的运算较为简单,有如下。
t1 = (11, 2, 13, 4)
t2 = (6, 12, 88, 10)
print(t1+t2)
print(t1*2)
print(len(t1), len(t2))
print(max(t1), min(t2))
print(sum(t1), sum(t2))
print(t1.index(13))
print(t2.count(10))
2.6 关于元组是不可变的
可读不可写
三、数据类型 -- 集合(set)【用的不多,了解即可】
3.1 集合是什么?
集合是一个无序的[没有下标索引的] 不重复的[去重] 序列,所有元素放在 {} 里面,中间以逗号隔开。
有序序列:有下标索引,字符串、列表、元组
无序序列:集合、字典
l = []
t = ()
set1 = set()
# 因为字典也用{}括起来,所以不能用{}创建空集合,必须使用内置函数set()
print(type(s), type(l), type(t), type(set1))
# 创建一个只包含一个元素的集合
set2 = {1}
print(type(set2))
集合支持集合推导式(Set comprehension):
使用推导式,创建一个包含100以内能被3和5整除的数的集合
使用推导式,创建一个集合,元素在'welcome to hqyj'中但不在'hello'中
set1 = {i for i in range(100) if i%3==0 and i%5==0}
print(set1)
set2 = {i for i in 'welcome to shanghai' if i not in 'hello'}
print(set2)
# 集合有去重性
set3 = {i for i in 'aaaaaaa'}
print(set3)
3.2 添加元素
(1)将元素 x 添加到集合 set 中,如果元素已存在,则不进行任何操作,语法格式如下:set.add(x)
(2)还有一个方法,也可以添加元素,且参数可以是列表,元组,字典等,语法格式如下:set.update(x) x 可以有多个,用逗号分开。
set1 = {1, 2, 3, 4, 5}
set1.add(3)
print(set1)
set1.add(66)
print(set1)
set1.update((77,88,99))
print(set1)
3.3 移除元素
- 将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误,语法格式如下:set.remove(x)
- 移除集合中的元素,且如果元素不存在,不会发生错误。格式如下所示:set.discard(x)
- 我们也可以设置随机删除集合中的一个元素,语法格式如下:set.pop()
- 我们也可以使用clear()清空集合元素
set1 = {'3zhangsan', '5lisi', '2wangwu', '4xiaohua'}
set1.remove('5lisi')
print(set1)
set1.discard('shanghai')
print(set1)
set1.pop()
print(set1)
set1.clear()
print(set1)
set 集合的 pop 方法会对集合进行无序的排列,然后将这个无序排列集合的左面边第一个元素进行删除。
3.4 集合的数学运算
a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7}
print("a与b的交集", a & b)
print("a与b的并集", a | b)
print("a与b的异或集", a ^ b)
print("a与b的差集", a - b, b - a)
s1 = {1, 2, 3}
s2 = {1, 2, 3, 4, 5}
print("s1是s2的子集吗?", s1 <= s2)
print("s1是s2的真子集吗?", s1 < s2)
分别有两个集合 st1 = {1,2,1,3,4,5,6,7} st2 ={2,5,6,9,5,8,75}
要求: 1. 求出他们之间的交集
2. 求出他们之间的并集
3. 求出他们之间的差集(分别求出st1-st2 和 st2-st1)
4. 求出他们之间的异或集
str1 = {1,2,1,3,4,5,6,7}
str2 = {2,5,6,9,5,8,75}
print('str1和str2的交集为:',str1 & str2)
print('str1和str2的并集为:',str1 | str2)
print('str1和str2的差集为:',str1 - str2)
print('str2和str1的差集为:',str2 - str1)
print('str1和str2的交叉补集为:',str1 ^ str2)
3.5 集合内置方法【了解即可】
方法 | 描述 |
add() | 为集合添加元素 |
clear() | 清空 |
copy() | 拷贝一个集合 |
difference() | 返回多个集合的差集 |
difference_update() | 移除集合中的元素,该元素在指定的集合也存在。 |
discard() | 删除集合中指定的元素 |
intersection() | 返回集合的交集。 |
intersection_update() | 返回集合的交集。 |
isdisjoint() | 判断两个集合是否包含相同的元素,如果没有返回 True,否则返回 False。 |
issubset() | 判断指定集合是否为该方法参数集合的子集。 |
issuperset() | 判断该方法的参数集合是否为指定集合的子集 |
pop() | 随机移除元素 |
remove() | 移除指定元素 |
symmetric_difference() | 返回两个集合中不重复的元素集合。 |
symmetric_difference_update() | 移除当前集合中在另外一个指定集合相同的元素,并将另外一个指定集合中不同的元素插入到当前集合中。 |
union() | 返回两个集合的并集 |
update() | 给集合添加元素 |
3.6 练习题
(1) 部门员工统计: 经理有:曹操,刘备,孙权 技术员:曹操,孙权,张飞,关羽 用集合完成以下要求: 1.既是经理也是技术员的有谁?
2.是技术员但不是经理的人有谁?
3.张飞是经理吗?
4.身兼一职的人有谁?
managers = {'曹操', '刘备', '孙权'}
technicians = {'曹操', '孙权', '张飞', '关羽'}
print('既是经理也是技术员的有:',managers & technicians)
print('是技术员但不是经理的人有:',technicians - managers)
print('张飞是经理吗?', '张飞' in managers)
print('身兼一职的人有:',managers ^ technicians)
(2)IEEE 和 TIOBE 是两大热门编程语言排行榜。截至 2018 年 12 月, IEEE榜排名前五的语言是:Python、C++、C、Java 和 C#。 TIOBE榜排名前五的语 言分别是:Java、C、Python、C++和 VB.NET。 请编程:
1、上榜的所有语言
2、两个榜单中同时出现的语言
3、只在 IEEE 榜中前五的语言
4、只在一个榜中出现的语言
IEEE = {'Python', 'C++', 'C', 'Java', 'C#'}
TIOBE = {'Java', 'C', 'Python', 'C++', 'VB.NET'}
print('上榜的所有语言:', IEEE | TIOBE)
print('两个榜单中同时出现的语言:', IEEE & TIOBE)
print('只在 IEEE 榜中前五的语言:', IEEE - (TIOBE - IEEE))
print('只在一个榜中出现的语言:', (IEEE - TIOBE) | (TIOBE - IEEE))
(3) 生成了 N 个 1~100 之间的随机整数(N<=1000),N 是用户输入的; 对于其中重复的数字,只保留一个,把其余相同的数字去掉;
1、随机整数的运用
2、合理利用集合去重
import random
N = int(input('请输入随机整数的个数:'))
set1 = {random.randint(1,100) for i in range(N)}
print(len(set1))
print(set1)
四、数据类型 -- 字典(dictionary)
4.1 字典是什么?
数据元素是键值对【键和值用冒号相连】,多个键值对元素放在 {} 里面,中间以 逗号 隔开。
注意:
- 键是唯一的,若有多个,只保留最后一次赋值的结果。
- 键还必须是不可变数据类型——字符串、数值、元组。
4.2 创建字典
str1 = ""
list1 = []
tuple1 = ()
set1 = set()
dict1 = {}
print(type(str1), type(list1), type(tuple1), type(set1), type(dict1))
d1 = {'name':'张三', 'age':18, 'sex':'男'}
print(d1)
d2 = dict(zhangsan=18, lisi=20, wangwu=19)
print(d2)
d3 = dict([('zhangsan',18), ('lisi',20), ('wangwu',19)])
print(d3)
name = ['张三', '李四', '王五']
d4 = dict.fromkeys(name, 18)
print(d4)
4.3 访问、遍历字典
字典是无序序列,没有下标索引。但是可以把相应的键放入到方括号中,通过键去访问值,就像我们查字典是一样的,键就是那个‘人字旁’, 通过'人字旁'的索引查到所有的值。
dict1 = {'人字旁':['你', '他', '们'], '木字旁':['树', '林', '村']}
print(dict1)
print(dict1['木字旁'])
# print(dict1['走之旁'])
# KeyError: '走之旁'
遍历字典的键、值、键值对
dict1 = {'人字旁':['你', '他', '们'], '木字旁':['树', '林', '村']}
# for i in dict1:
# print(i)
#
# for i in dict1:
# print(dict1[i])
for i in dict1.keys():
print(i)
for i in dict1.values():
print(i)
for i in dict1.items():
print(i)
4.4 修改字典
通过键的索引,赋值修改值即可。键存在,就修改;键不存在,就添加在末尾。
d1 = {'name':'张三', 'age':18, 'sex':'男'}
# 存在键,修改
d1['age'] = 20
print(d1)
# 不存在键,添加
d1['score'] = 100
print(d1)
'''
字符串 s[0] = '66' 报错——不可变
列表中 l[0] = 66
元组中 t[0] = 66 报错——不可变
集合中 st[0] = 66 报错——无序序列,无下标
字典中 d['age'] = 20
'''
4.5 删除字典元素
(1)pop() 以键做参数
(2)popitem() 无参
(3)clear() 清空
(4)del 删除
d1 = {'name':'张三', 'age':18, 'sex':'男'}
d1.pop('name')
print(d1)
d1.popitem()
print(d1)
d1.clear()
print(d1)
del d1
print(d1) # 报错
4.6 字典键的特性
(1)不可变
(2)唯一
d1 = {'name':'张三', 'age':18, 'sex':'男'}
for i in d1.keys():
i = 'xxxx'
print(d1)
d2 = {'name':'张三', 'age':18, 'sex':'男', 'age':20}
print(d2)
# 运行结果
# {'name': '张三', 'age': 18, 'sex': '男'}
# {'name': '张三', 'age': 20, 'sex': '男'}
4.7 字典内置函数&方法
描述 | 函数 |
清空 | dict.clear() |
返回一个字典的浅复制 | dict.copy() |
创建一个新字典,以序列seq中元素做字典的键,val为字典所有键对应的初始值 | dict.fromkeys() |
返回指定键的值,如果键不在字典中返回 default 设置的默认值 | dict.get(key, default=None) |
如果键在字典dict里返回true,否则返回false | key in dict |
以列表返回一个视图对象 | dict.items() |
返回一个视图对象 | dict.keys() |
和get()类似, 但如果键不存在于字典中,将会添加键并将值设为default | dict.setdefault(key, default=None) |
把字典dict2的键/值对更新到dict里 | dict.update(dict2) |
返回一个视图对象 | dict.values() |
删除字典 key(键)所对应的值,返回被删除的值。 | pop(key[,default]) |
返回并删除字典中的最后一对键和值。 | popitem() |