python(二)——list、字典、字符串操作
列表——list
假设一种场景,想要存班里所有同学的名字,那应该拿什么存呢?
我们可以拿一个字符串去存,例如:
stus = "s1,s2,s3,s4,s5……sn"
那我们要从里面把某一个学生取出来,或者说,想要统计班级内有多少学生,这种方式可以是可以,但是未免太麻烦,假设被别人看见你这么写,就可以卷铺盖回家了;为了里面我们被卷铺盖回家,我们可以怎么做?
答案是用: list(列表)
比如说:
stus = ['s1','s2','s3','s4',……,'sn',]
定义一个数组很简单,中括号内,每一个元素用逗号隔开 ,里面元素的类型不一定要一致,可以为 int ,也可以为 str 类型,下标从 0 开始。
定义一个空列表,有两种方式:
stus = []
stus = list()
那么我们这一个 list ,怎么对它进行操作,也就是增删改查呢?
增
append、insert
stus.append('鲁班') #在 list 的末尾增加一个元素 stus.insert(9,'程咬金') #在指定的位置插入元素 stus.insert(999,'后羿') #在指定的位置插入元素,假设位置不存在,那么默认把元素插入到最后
查
list 都是从下标开始取值
print('单个取',stus[0]) # 第一个元素 print('最后一个元素',stus[-1]) # 最后一个元素 print('倒数第二个元素',stus[-2]) # 倒数第二个元素 print('改之前的',stus) # 整个列表
改
找到 list 的元素下标重新赋值
stus[4] = '马可波罗' # 将下标为 4 的元素改成马可波罗
但是,这里注意不要瞎赋值,假设赋值的下标超过最大值报错: IndexError: list assignment index out of range
删
pop、del、remove
stus.pop(0) # 删除指定位置的元素 stus.pop() # 默认删除list里面最后一个元素 del stus[0] # 删除指定的位置的元素 del stus # 如果不跟下标,那么整个 list 会被删除 stus.remove("后羿") # 删除指定的元素,如果 list 里面有多个一样的元素,那么就只会删掉一个(假设不知道下标,可用此方法)
那么有个特殊情况,假设我们删除的下标不存在,或者说要移除的元素不存在,是会报错:ValueError: list.remove(x): x not in list;IndexError: pop index out of range
其他常用方法
我们根据场景来看一些方法
1、假设我们要判断一个 list 内某元素存不存在,或者说 list 内某元素的个数,用什么方法?
count = stus.count('程咬金') # 某个元素在list里面的数量
2、把一个已经存在的 list 清空
stus.clear() # 清空 list
3、将一个 list 重新复制一份
new_stus = stus.copy() # 复制一个stus 列表,存为 new_stus
4、将 list 反转,第一个为最后一个,第二个为倒数第二个
stus.reverse() # 反转 print(stus)
5、将 list 排序
nums = [9,23,12,234,23,5235,235,235,23523,523] nums.sort() # 从小到大升序排列 nums.sort(reverse=True) # 里面加个反转,也就是从大到小排列 print(nums)
6、将两个 list 拼接,有两个方式
stus.extend(nums) #把 nums 的元素,加入到 stus 里面 print(stus) list3 = list1 + list2 # 将 list 1 和 list 2 拼接
7、要找出一个元素在 list 的下标,要注意,这里只是显示在 list 内的第一个下标,而且元素不存在是会报错的:ValueError: '程咬金' is not in list
result = stus.index('程咬金') # 找某个元素的下标
8、判断一个元素是否在 list 内
if username not in usernames: print('username 不在 list 里面') if username in usernames: print('username 在 list 里面')
9、切片,假设有一个 list ,我们不同的步长打印出的结果也不一致,具体方式为:[::num](num 为所要打印的步长,为负数就逆向打印)
>>> shoplist = ['apple', 'mango', 'carrot', 'banana'] >>> shoplist[::1] ['apple', 'mango', 'carrot', 'banana'] >>> shoplist[::2] ['apple', 'carrot'] >>> shoplist[::3] ['apple', 'banana'] >>> shoplist[::-1] ['banana', 'carrot', 'mango', 'apple']
10、如何知道一个 list 的长度呢?
nums = [1,2,3,4,5]
len(nums)
11、切片
切片的作用就是按一定的规则从 list 内取出元素,比如说我们要取出一个 list 的后面 3 个元素,因为取下标只能一个一个取,如果我们想一次性取出来做一个 list ,有简单的方式就是切片
需要注意的是,切片顾头不顾尾,而且不只是 list ,有下标的都能切,比如说字符串
l = [1,2,3,4,5,6] print(l[1:]) #从下标 1-最后一位 print(l[:]) #取整个 list print(l[1:4]) #下标1-3位 print(l[::-1]) # 反向打印,如果步长为负数,那么取值的时候从右往左
小结:
方法名 | 功能 | |
增 | append | 在末尾增加元素 |
insert(1,'xxx') | 在下标为 1 前插入 xxx | |
查 | stus[0] | list[下标] |
改 | stus[4] = '马可波罗' | list[下标] = 新值 |
删 | pop(1) | 删除下标为 1 的,不传值删除最后一位 |
del stus[0] | 删除下标为 0 的元素 | |
remove('xxx') | 删除 list 内的 xxx | |
常用方法 | count('xxx') | 查询 xxx 在 list 内的数量 |
clear() | 清空 list | |
copy() | 将 list 复制出来 | |
reverse() | 将 list 反转 | |
sort() | 将 list 排序 | |
extend() | list 拼接 | |
index('xxx') | 找 xxx 元素的的下标 | |
in/not in | 判断某元素是否在 list 内,返回布尔值 | |
[::num] | 切片 | |
len(stus) | 返回 list 的长度 |
多维数组
判断几个维度,看有几个中括号就 ok 了
nums1 = [1,2,3,4,5,['a','b','c','d']] # 2 维数组 nums2 = [1,2,3,4,['a','b','c','d',['test','dev','pre']]] # 3 维数组
其实,我们的多维数组,也就是将子 list 看成是上一级 list 的一个元素而已
那假设我们要取 nums1 里面的 ‘c’,如何取?
print(nums1[5][2])
有趣的是,其实一个字符串也可以当成是一个 list 来看,比如说我们要取,nums2 list 里面的 dev 中的 'e' ,怎么取?
print(nums2[4][4][1][1])
练习
一、
- 用 list 存账号和密码
- 需要校验 用户不存在的话 要提示
- 需要校验是否为空
- 账号密码正确登录成功,提示当前日期
- 最多输错3次
解决方案:
- 输入账号密码
- 校验是否输入为空
- 校验账号是否存在 list.count()
- 从usernames里面找到user的下标,然后去password种去对应的密码
usernames = ['cwl','pn','gxn','hyp'] passwords = ['123456','abc123','324234','23423'] import datetime today = datetime.datetime.today() count = 0 # for i in range(4): while count<3: count+=1 username = input('username:').strip()#去掉一个字符串两边的空格 password = input('password:').strip() if username=='' or password=='': print('账号/密码不能空!') # elif usernames.count(username)==0: #判断元素的个数 elif username not in usernames: #判断元素是否存在某个list里面 print('用户不存在!') else: user_index = usernames.index(username)#登录用户的下标 p = passwords[user_index]#根据下标取到密码 if password == p:#判断密码是否正确 print('欢迎%s登录,今天的日期是%s.'%(username,today)) break else: print('密码错误!') else: print('错误次数已经用尽')
注意:最后面的 else 是对应 for 循环的,当 for 循环正常全部执行完,那么就会去执行 else,可以发现我们的 for 循环内加了一个 break ,假设 for 循环被 break 住了,就不会去执行 else内的内容。这里再提一句 break 和 continue 的区别:
break 语句用于中断循环语句,也就是中止循环语句的执行,要注意的是:中断了 for 循环/while 循环,相应循环的 else 模块将不被执行
continue 语句是告诉 Python 跳过当前循环块中剩余的语句,并继续该循环的下一次迭代
二、写一个 sql 插入的语句,要求在 user 的 list 每个用户名字前面加上字母标志:bt-
复杂的方式1:取下标循环
stus = ['chengweiliang','chenqi','guoliwen'] password='123456' index = 0 username='' while index<len(stus): username = stus[index] username = 'szz-'+username sql='insert into user (username,password) value ("%s","%s");'%(username,password) print(sql) index+=1
复杂的方式2:
for i in range(len(stus)): #b username = stus[i] print(username) sql='insert into user (username,password) value ("%s","%s");'%(username,password)
简单的方式(推荐):直接循环。for 循环直接循环一个 list ,就是取 list 里面的每一个元素
stus = ['chengweiliang','chenqi','guoliwen'] password = '123456' for stu in stus: # for循环直接循环一个 list,就是取 list 里面的每一个元素,这里的 stu 是随意命名的,直接用 i 也成,这个只是为了增强可读性 print('每次循环取的值',stu) username = 'bt-'+stu print(username) sql='insert into user (username,password) value ("%s","%s");'%(username,password)
列表生成式
假设我们要有一个 list ,要将其变成一个两位的数数组(一位的前面补零),那么按照我们传统的方式来做就是:
l = [] for i in range(1,11) l.append(str(i).zfill(2))
那么有没有高级的做法?有的,叫列表生成式:
l2 = [str(i).zfill(2) for i in range(1,11)]
字典——dict
假设我们要存一个班级内学生的信息:用户名,密码,电话,住址……
那如果还用 list 来存,最好的方式就是做一个二维数组:
stus = [ ['鲁班','123','1112','sdfsdf',[1,2,3,4] ], ['后裔','123','1112','sdfsdf',200,'北京'], ['程咬金','123','1112','sdfsdf',100], ['狄仁杰','123','1112','sdfsdf',200], ]
但这样看起来并不直观,而且取数很麻烦,那么更好的方式是什么呢?
字典的方式:以一种 key-value 键值对方式来存
字典是一种key-value的数据类 型,比如说要存每个人的信息,那么每个人的编号就是key,value就是每个人的信息,这样的话,一个字典就能存所有人的信息了。字典的定义使用{}, 大括号,每个值用“,”隔开,key和value使用“:”分隔
stu_info = { 'username':'gzw', 'password':'123456', 'money':20, 'addr':'广州' }
为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。
第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢,这种就是字典的实现方式。
字典的特性:
字典是无序的,因为它没有下标,用key来当索引,所以是无序的
字典的key必须是唯一的,因为它是通过key来进行索引的,所以key不能重复,天生就去重
那么我们来介绍一些字典的常用操作
新增字典
d1 = {} #创建空字典 d2 = dict() #创建空字典
增
d1['name'] = '后裔' d1['age'] = 18 d1.setdefault('class','双子座') # 这个增加的 key 是增加默认 key 值。如果使用 setdefault,key已经存在了,就不会修改原来key的值,setdefault 相当于一个初始化操作,不具备修改功能。如果这个key存在的话,那就不动它,不存在的话,添加一个 print('之前的',d1) d2 = {'abc':1234} d1.update(d2) # 在 d1 字典内增加一个 d2 字典,更新字典值,如果key存在的话,就更新,不存在的话就添加 print(d1)
改
只有一种方式
d1['name']='甄姬'
查
print(d1['name']) # 当 key 不存在时,会报错:KeyError print(d1.get('money')) # 当 key 不存在时,不会报错,返回一个 None print(d1.get('money',0)) # 当 key 不存在,返回默认值为 0 print(d1.keys()) # 取到字典里面所有的key,存为一个 list print(d1.values()) # 取到字典里面所有的value,存为一个 list
删
d1.pop('name') # 删除 key 为 name del d1['name'] # 删除 key 为 name d1.popitem() # 随机删除一个 key d1.clear() # 清空整个字典
其他常用方法
1、打印所有的 key/value
print(d1.keys()) # 取到字典里面所有的key,存为一个 list print(d1.values()) # 取到字典里面所有的value,存为一个 list
2、如果这个key存在的话,那就不动它,不存在的话,添加一个
d1.setdefault('class','双子座')
3、更新字典值,假设 key 存在,则直接更新 value,不存在 key ,则新增该 key-value
d2 = {'abc':1234} d1.update(d2) # 在 d1 字典内增加一个 d2 字典,更新字典值,如果key存在的话,就更新,不存在的话就添加
4、将字典转化成一个 list
print(dic.items()) # 字典转换成一个list
5、循环字典
dic = {'stu1':'cc','stu2':'andashu','stu3':'niuniu'} for k in dic: print(k,dic[k]) # 打印key和value的值,推荐使用这种方式,速度快 for k,v in dic.items(): print(k,v) # 打印key和value的值,这种方式不推荐,因为会把字典转换成列表,效率不高
小结:
方法 | 功能 | |
新增字典 | d1 = {} | 新增空字典 |
d2 = dict() | 新增空字典 | |
增 | d1.['key'] = 'value' | 新增一对 key-value |
改 | d1.['key'] = 'new_value' | 将 key 的值改为 new_value |
查 | d1['key'] | 查 key 值对应的 value,key 值不存在会报错 |
d1.get['key'] | 当 key 不存在时,返回 None | |
删 | d1.pop('key') | 删除 key |
del d1['key'] | 删除 key | |
d1.popitem() | 随机删除一个 key | |
d1.clear() | 清空整个字典 | |
其他方法 | print(d1.keys()) | 以一个 list 形式打印所有 key 值 |
print(d1.values()) | 以一个 list 形式打印所有 value 值 | |
d1.setdefault('key','value') | 如果 key 存在就不变,不存在就增加 | |
d1.update(d2) | 如果 key 存在就更新,不存在就增加 | |
d1.items() | 把字典转化成一个 list | |
for i in d1:print(i,dic[i]) | 循环取值,其实就是取到 key | |
if key in d1:print(key 存在) |
判断 key 是否存在 |
练习
一、
我们有一个 list ,里面存的是字典,现要求:
- 统计一下现有学生总共有多少金币
- 找出金币小于100的学生姓名
- 金币大于500的学生,扣去300金币,小于等于100的人,加上200金币
users = [ { "id": 2, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑123", "grade": "双子座123", "phone": "12123654311", "gold": 34000 }, { "id": 8292, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123676705", "gold": 100 }, { "id": 8308, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123610039", "gold": 100 }, { "id": 8309, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123675980", "gold": 100 }, { "id": 8310, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123629672", "gold": 100 }, { "id": 8311, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123689607", "gold": 100 }, { "id": 8312, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123638612", "gold": 100 }, { "id": 8313, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123628322", "gold": 100 }, { "id": 8314, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123663283", "gold": 100 }, { "id": 8315, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123634676", "gold": 100 }, { "id": 8316, "name": "矿泉水", "sex": "未知", "age": 38, "addr": "天通苑", "grade": "双子座", "phone": "12123680540", "gold": 100 }, { "id": 9909, "name": "矿泉水", "sex": "男", "age": 15, "addr": "中国湖南", "grade": "双子座", "phone": "12345679999", "gold": 100 }, { "id": 10277, "name": "矿泉水", "sex": "男", "age": 18, "addr": "北京市昌平区", "grade": "双子座", "phone": "15249211246", "gold": 100 } ]
解决方案:
1、统计一下现有学生总共有多少金币
- 循环users这个list
- 从每个user的字典里面取到gold
- 把每次的gold值相加
2、找出金币小于100的学生姓名
- 循环users这个list
- 从每个user的字典里面取到gold
- 判断gold的值是否小于100
3、金币大于500的学生,扣去300金币,小于等于100的人,加上200金币
- 循环users这个list
- 从每个user的字典里面取到gold
all_gold = 0 #存放所有的金币 for user in users: gold = user.get('gold') all_gold = gold+all_gold # all_gold += user.get('gold') if gold<=100: print('%s的金币小于等于100'%user.get('name')) user['gold'] = gold+200 if gold>500: user['gold'] = gold - 300 print(users)
二、
现在有一个 list ,把字典里面每个用户的密码,前面都加上 username_ +
users = { "gzw1":'123456sdf', "gzw2":'123456sd', "gzw3":'123456sdf', "gzw4":'1234sdf56', "gzw5":'12345gsdfs6', "gzw6":'1234324g56', }
解决方案:
1、循环这个字典
2、把value修改成value = key_+value
方式1:
for k in users:#直接循环一个字典的话,循环的是key value = users[k] #通过key取到value users[k] = '%s_%s'%(k,value) print(users)
方式2:转化成 list 操作
for k,v in users.items(): print('%s===>%s'%(k,v)) users[k] = '%s_%s' % (k, v)
三、
stus = { "胖妞": { "house": ['三环', "四环", "七环"], "car": { "日本": ["雷克萨斯", "英菲尼迪"], "中国": ['五菱宏光', '红旗', '比亚迪', "宝骏"], "美国": ["福特", "凯迪拉克"] }, "化妆品": { "SK-2": 1000, "YSL": 8000 } }, "陆明":{ "money":[1000,5000,8000,800000], "xifu":{ "越南":2, "伊拉克":10, "韩国":2, "泰国":3 } } }
1、统计一下胖妞总共有多少辆车
car = stus['胖妞']['car'] # car.update(new_car) all_count = 0 for c in car.values(): all_count = len(c)+all_count print('胖妞总共有%s辆车'%all_count)
2、胖妞又买了,德国车2辆,奥迪、奔驰
stus['胖妞']['car']['德国'] = ['奥迪','奔驰']
3、胖妞的化妆品全被男朋友扔了
suts[''胖妞].remove('化妆品')
4、胖妞买了套房子在四环
house = stus['胖妞']['house'] house.append('四环')
5、胖妞把比亚迪换成了保时捷
stus['胖妞']['car']['中国'][2] = '保时捷'
字符串处理
字符串是不能修改的
定义一个字符串:
s = " ab c cc c "
users='abc,xiaozi,xiaobai,xiaohei,xiaoming,xiaolan'
li = ['abc', 'xiaozi', 'xiaobai', 'xiaohei', 'xiaoming', 'xiaolan']
s.strip() | 去除字符串两边的空格,换行符 |
s.strip('c') | 去掉字符串两边的字符 'c' |
s.lstrip() | 去除左边的空格以及换行符 |
s.rstrip() | 去除右边的空格以及换行符 |
s.count('c') | 字符串内字符 'c' 的个数 |
s.index('d') | 字符串内第一个 'd' 的下标,不存在会报错 |
s.find('d') | 字符串内第一个 'd' 的下标,不存在会返回 -1 |
s.capitalize() | 首字母大写 |
s.upper() | 全部变成大写 |
s.lower() | 全部变成小写 |
s.replace("c","C") | 将 'c' 替换为 'C',默认全局替换。可用于清除字符串内的空格以及换行 |
s.replace("c","C",1) | 只替换第一个 'c',最后传的为个数 |
s.endswith('xxx') | 判断是否以 'xxx' 为结尾,可用来判断上传文件的格式,返回布尔类型 |
s.startswith('xxx') | 判断是否以 'xxx' 为开头,返回布尔类型 |
s.center(50,'*') | 将 s 字符串扩充到 50 个字符,不够的话,左右用 * 号补齐,s 在最中间 |
s.isspace() | 判断 s 是否为空格,如果为空,会返回 False |
s.islower() | 判断 s 是否为全小写,返回布尔类型 |
s.isupper() | 判断 s 是否为全大写,返回布尔类型 |
s.isalnum() | 判断 s 有无特殊符号:@#等;s 为数字或字母为 True |
s.isalpha() | s 不是数字,特殊符号,就返回 True |
s.isdigit() | s 为整数,返回 True |
'1'.zfill(5) | 将数字前面补 0 到 5 位 |
s.format() | 格式化输出 |
s.format_map() | 格式化输出,传的值为字典形式 |
users.split(',') | 将 users 字符串用 ',' 分割;括号内不传值,默认用空格分开 |
','.join(li) | 将 li 这个 list 转成字符串,用','连接 |
格式化输出
1、直接 + 号
2、用 %s 号占位符,注意参数的格式
username='abc' today = '2019-03-30' print( '欢迎%s登陆,今天的日期是%s.'%(username,today))
% 占位,不一定要加 s ,s 是代表 string ,还有其他用法,常见的:%d 和 %f ,%d 代表 digital - 整数;%f 代表 float - 浮点数小数
要注意的是:
%f 默认保留 6 位小数,也可指定位数,假设 %.2f 代表保留两位小数
%d 是默认只取整数位置,就比如说下面的例子,就算 age = 18.02822,打印出来也是 18
%d 和 %f 对应的参数类型必须为整数或者小数,假设 age = 'gzw',那么就会报错了
%s 就没有限制,什么都能打印出来,但是规范用法最好是根据数字类型来指定输出的类型
username = '小黑' age = 18 high = 1.78 s1 = '欢迎 %s登录,它的年龄是 %d 它的身高是 %f '%(username,age,high) print(s1)
3、format()
username='abc' today = '2019-03-30' print( '欢迎{}登陆,今天的日期是{}.'.format(username,today))
更直观好看的:
s3="insert into user value ({username},{password},{phone})" new_s3 = s3.format(password="123",username='abc',phone='110') print(new_s3)
4、format_map(),用字典形式传值
s3="insert into user value ({username},{password},{phone})" new_s3 = s3.format_map({"password":123, 'username':'ccc', 'phone':110 }) print(new_s3)
分割
假设有一个字符串:users='abc,xiaozi,xiaobai,xiaohei,xiaoming,xiaolan',每个逗号之间存的是用户名,假设我们要将其取出,每个名字之前加入'bt-',怎么弄?
将其变成一个 list 就好弄了,那么怎么弄呢?
result = users.split(',') for use in users: use = 'bt-'+use
那么有个特殊情况,假设我们的分割符号不在字符串内,那么会将整个字符串作为一个 list ,也就是:['abc,xiaozi,xiaobai,xiaohei,xiaoming,xiaolan']
那么反过来咋办?一个 list 如何转化成一个字符串
li = ['abc', 'xiaozi', 'xiaobai', 'xiaohei', 'xiaoming', 'xiaolan']
list = ','.join(li)
元组
元组很简单,元组是一种不可变的数组,理解为不可修改的 list,什么情况下被用到呢?假设我们要定义一个东西,不希望被修改,那么可以用元组来定义。比如说数据库的连接配置
添加
元组的定义方式:
t = ('127.0.0.1',3306,'root','123456')#元组
操作
既然元组不能被修改,那么它的可操作性也就少了很多,就是不能修改/删除,但是也可以循环取值等
t = ('127.0.0.1',3306,'root','123456') # 元组 t.count(3306) # 查找 3306 的个数 t.index(3306) # 查找第一个 3306 的下标 print(t[1]) # 打印下标为 1 的元素
集合
记住一点:集合天生可以去重,且无序!!!
定义一个集合
l = [1,2,3,3,4,4] res = set(l) print(res)
刚刚我们说过,集合天生去重,那么这里 print 出来的值应该为:
{1, 2, 3, 4}
那么,集合我们可以大概知道是啥,那么集合就有几个方法可以用,基本的取交集并集差集要会,还有一些奇葩的集:对称差集
交集
交集很简单,假设 a、b 两个集合,交集 = a∩b,也就是取 a 和 b 共有重叠的那部分
s1 = {1,2,3,4} s2 = {4,5,6,7} print(s1.intersection(s2)) #取交集 print(s1 & s2) #取交集
并集
并集就是 a 和 b 结合起来
s1 = {1,2,3,4} s2 = {4,5,6,7} print(s1.union(s2)) print(s1 | s2)
差集
差集就是 b 里面除掉 a 和 b 都有的那部分
s1 = {1,2,3,4} s2 = {4,5,6,7} print(s2 - s1) # s2 里面有,s1 里面没有的 print(s1.difference(s2))
对称差集
对称差集,就是 a 和 b 的并集除去 a 和 b 的交集那部分
s1 = {1,2,3,4} s2 = {4,5,6,7} print(s1.symmetric_difference(s2)) # 把a和b里面都有的去掉 print(s1^s2)
集合操作
集合是不重复且无序的,那么也就没什么下角标的说法,能操作的也比较简单,也可以做添加元素,也能循环。删除以及增加的功能如下:
s1 = {1,2,3,4} s2 = {4,5,6,7} s1.add('abc') s1.remove('abc') if 'abc' in s1: print('在集合内')
练习
要求输入内容必须包含大写字母、小写字母、数字、特殊字符
import string password = input('请输入密码:').strip() if password: print('输入不为空') else: print('密码不能为空') p_set = set(password) print('大写字母取',p_set.intersection(set(string.ascii_uppercase))) print('小写字母取',p_set.intersection(set(string.ascii_lowercase))) print('数字取',p_set.intersection(set(string.digits))) print('特殊字符取',p_set.intersection(set(string.punctuation))) if p_set.intersection(set(string.ascii_uppercase)) and p_set.intersection(set(string.ascii_lowercase)) and p_set.intersection(set(string.digits)) and p_set.intersection(set(string.punctuation)): print('密码合法') else: print('密码必须包含大写字母、数字、特殊字符串')
作业
1、写一个注册的程序
- 注册的账号密码存在文件里面
- 密码不能为纯数字
- 已经存在的账号要提示该账号已经被注册
- 账号和密码长度要大于6小于13位
- 两次密码输入一致才可以
- 要校验输入不能为空
f = open('users.txt') file_content = f.read() f.close() users = {} if len(file_content)==0: pass else: user_passwd_list = file_content.split(' ') for l in user_passwd_list: username = l.split(',')[0] passwd = l.split(',')[1] users[username] = passwd for i in range(3): u = input('username:').strip() pwd = input('password:').strip() pwd2 = input('cpwd:').strip() if len(u)<6 or len(u)>13: print('用户名长度不合法') elif len(pwd)<6 or len(pwd)>13: print('密码长度不合法') elif pwd.isdigit(): print('密码不能是纯数字') elif pwd!=pwd2: print('两次输入的密码不一致') elif u in users: print('用户已经被注册') else: users[u] = pwd print('注册成功!') break f = open('users.txt','w') for u,p in users.items(): f.write('%s,%s '%(u,p)) f.close()
2、登录
- 账号密码从注册产生那个文件里面取
- 登录的时候账号大小写不区分
f = open('users.txt') file_content = f.read() f.close() users = {} if len(file_content)==0: pass else: user_passwd_list = file_content.split(' ') for l in user_passwd_list: username = l.split(',')[0] passwd = l.split(',')[1] users[username] = passwd count = 0 # for i in range(4): while count<3: count+=1 username = input('username:').strip()#去掉一个字符串两边的空格 password = input('password:').strip() if username=='' or password=='': print('账号/密码不能空!') elif username not in users: print('账号不存在!') elif password == users.get(username): print('登录成功!') else: print('账号/密码错误!') else: print('错误次数已经用尽')
3、产生一批测试账号,存到文件里面
- 输入一个数字,就产生多少条
- 长度是10,账号包含字母和数字
- sdfs234sdf@163.com
- sdfs234sdf@163.com
- sdfs234sdf@163.com
import string import random num = input('number:').strip() if not num.isdigit(): print('请输入整数!') else: file = open('account.txt','w') num = int(num) for i in range(num): t1 = random.sample(string.digits,5) t2 = random.sample(string.ascii_letters,5) result = ''.join(t1+t2)+'@163.com'+' ' file.write(result) file.close()