列表——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 } ]