目录
一、列表
列表List(用 [ ] 标识)是Python 中使用最频繁的数据类型。可以完成大多数集合类的数据结构实现,支持字符,数字,字符串甚至可以包含列表(即嵌套)。下标为空表示取到头或尾。
列表和元组的区别:
- 元组不可变:只能读元素,不可修改
- 列表可变:可读可写
1)创建列表:先创建空列表实例,再添加元素
python中不限制列表中元素的类型(元素可存放任意类型)
a = [] #空列表 实例化
b = list() #实例化
c = ["hello","python",1]
a.append("python") #添加元素
b.append("hello") #添加元素
print(type(a)) #<class 'list'>
print(type(b)) #<class 'list'>
print(type(c)) #<class 'list'>
2) 访问下标:注意防止下标越界。
打印列表最后一个元素:-1指的是最后一个元素(长度-1)
print(list[len(list)-1]) #打印列表list最后一个元素
print(list[-1]) #打印列表list最后一个元素
3)切片操作
取出列表中下标连续的一组元素,也相当于得到一个子列表(下标范围前闭后开)
除了获取某个确定下标的元素外,切片操作得到的是列表形式的数据
list = ['runoob', 786 , 2.23, 'john', 70.2]
tinylist = [123, 'john']
print(list) # 输出完整列表 ['runoob', 786 , 2.23, 'john', 70.2]
print(list[0]) # 输出列表的第一个元素 runoob
print(list[:-1]) #从前往后取数据,不包括最后一个元素
print(list[:]) #得到列表自身所有数据
print(list[1:3]) # 输出第二个至第三个元素 [786 , 2.23]
print(list[2:]) # 输出从第三个开始至列表末尾的所有元素 [2.23, 'john', 70.2]
print(tinylist * 2) # 输出列表两次 [123, 'john', 123, 'john']
print(list + tinylist) # 打印组合的列表 ['runoob', 786 , 2.23, 'john', 70.2,123, 'john']
切片操作,可以指定步长(步长为负数时,从后往前取数据):
list = [1,2,3,4,5,6,7,8]
print(list[::1]) #1是指定的步长 [1, 2, 3, 4, 5, 6, 7, 8]
print(list[1:7:2]) #2 是指定的步长 [2, 4, 6]
print(list[::-2]) #2 是指定的步长 [8, 6, 4, 2]
print(list[::-1]) #2 是指定的步长 [8, 7, 6, 5, 4, 3, 2, 1]
4)列表的遍历
取出列表中的每个元素,并进行某种操作
list = [1,2,3,4,5,6,7,8,9]
#方法一:
for elem in list:
print(elem)
elem = elem + 10 #不修改变量本身,只修改临时变量
print(elem)
#方法2:
for i in range(0,len(list)):
print(list[i])
list[i] = list[i]+10 #可修改每一个列表元素
print(list) #输出新的list
#方法3:使用while循环,通过下标遍历
i = 0
while 1 < len(list):
print(list[i])
i += 1
5)列表的新增(插入元素)
list列表可插入不同数据类型的元素,且append函数是搭配列表对象一起使用的。需要搭配对象使用的函数也叫“方法”
append:把元素插在列表最后
insert:插入到指定位置
expend:把新列表拼接到旧列表后面
list = [1,2,3,4,5]
list.append(0)
list.append('hello')
print(list) #[1, 2, 3, 4, 5, 0, 'hello']
list1 = ["hello","python"]
print(list.expend(list1)) #输出[1,2,3,4,5,"hello","python"]
print(list1.expend(list)) #输出["hello","python",1,2,3,4,5]
insert插入方法(指定下标处插入元素):
6)列表的修改:使用下标直接替换
a = ["1","2","python"]
a[0] = "hello"
print(a) #输出["hello","2","python"]
6)列表的查找
注意!!!索引不能超出列表长度
list = [1,2,3,4,5]
print(len(list)) #求列表长度:5
print(5 in list) #判断某个元素5是否存在于列表里
print(list.index(5)) #使用index获取元素5在列表中的位置
print(list.count(5)) #统计元素5出现的次数
7)列表的删除
- pop():删除末尾元素
- pop(i):删除i下标的元素
- remove(num): 删除列表中的num元素
- clear():清空元素,返回空列表
删除末位几个数据,连续几次pop操作即可
list = [1,2,3,4,5]
list.pop() #删除末尾元素 #[1, 2, 3, 4]
list.pop(2) #删除下标为2的元素 [1, 2, 4]
list.remove(4) #[1, 2]
print(list) #[1, 2]
company = input().split()
companylist = []
for i in company:
companylist.append(i)
#方法一
companylist.pop(0) #删除第一个元素
print(companylist)
#方法二
companylist.remove(companylist[0])
print(companylist)
给定两个字符串A和·B,删除A字符串中的B字符串:
friend = input().split()
argfriend = input()
friendlist = []
for i in friend:
friendlist.append(i)
friendlist.remove(argfriend)
print(friendlist)
8)列表的反转reverse和排序:
注意!!!列表反转reverse()和排序sort()不能直接和print放一起使用(如:print(num.sort())写法错误),分开两行才行,如下代码:
list = [1,9,7,100,2,3,4,5]
list.reverse()
print(list) # [5, 4, 3, 2, 100, 7, 9, 1]
list.sort()
print(list) # [1, 2, 3, 4, 5, 7, 9, 100]
9)列表的拼接: 列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
- 使用 + 拼接两个列表,不改变原列表
- 使用extend拼接(不需要变量会接收,没有返回值),相比“+”拼接更高效(把后一个列表拼接到前一个列表里),会改变原列表a的内容(拼接后是存储到新的变量a里,同时也会释放旧的变量a)
a = [1,2,3]
b = [6,7,8]
print(a + b) #[1, 2, 3, 6, 7, 8]
# c = a.extend(b) # 返回None,extend拼接不需要返回值
a.extend(b) #把b拼接到a列表里
print(a) #[1, 2, 3, 6, 7, 8]
print(b) #[6, 7, 8]
二、元组
元组中的元素值不允许删除,但可使用del语句来删除整个元组:del tup
元组之间可以使用 + 号和 * 号进行运算。可以组合和复制,运算后会生成一个新的元组。
元组不可变对象,相当于只读列表(不能修改),但是可以哈希
元组中只包含一个元素时,需要在元素后面添加逗号,如: tup1 = (50,)
1)创建元组:
元组(用 () 标识),元素可为任意类型。
a = () #创建一个空元组
b = tuple() #创建一个空元组
print(type(a))
print(type(b))
c = (1,2,'python',[1,2,3],[],True)
print(c) #(1, 2, 'python', [1, 2, 3], [], True)
print(type(c)) #<class 'tuple'>
2)元组访问:通过下标获取特定元素或者切片获取元组的某一部分
注意不能数组越界
c = (1,2,'python',[1,2,3],[],True)
print(c[1]) #2
print(c[-1]) #True
print(c[0:4]) #(1, 2, 'python', [1, 2, 3])
#for循环遍历:
for elem in c:
print(elem)
#判定元素是否存在:
print(2 in c) #判断元素2是否存在元组中
print(c.index(2)) #打印输出下标为2的元素
因为元组不可变,故不能进行修改、删除、新增操作,只能查看
3)元组与列表的转换
a = [1,2,3,4]
b = tuple(a) #列表a转化为元组b
c = (1,2,3,4)
d = list(a) #元组c转化为列表d
三、字典dict
字典("{ }"标识),是除列表以外最灵活的内置的键值(key-value)对组合而成的数据结构类型是一种可变容器模型。
- 键:唯一不可变的(可哈希的值):如字符串,数字或元组。
- 值:可以取任何数据类型,字典的操作都是围绕key展开的。
1)创建字典 (最后一个键值对后的逗号可有可无)
#创建字典
a = {}
b = dict()
#字典初始化:
a = {"id":1,"name":"张三","性别":"男"}
dict = { #推荐写法,可读性更高
"id":1,
"name":"张三",
"性别":"男"
}
2) 查找key
- in或者下标的形式[],两种方法都很高效(字典背后使用了哈希表)
对于列表list使用in查找是比较低效的(需要遍历),使用[ ]下标索引高效
dict = { #推荐写法,可读性更高
"id":1,
"name":"张三",
"性别":"男"
}
#判断键和值是否在字典里
print("id" in dict) #True
print("name" in dict) #True
#判断键和值不在字典里
print("id" not in dict) #False
print("python" not in dict) #True
#根据key查找对应的value
print(dict["id"]) #1
print(dict["性别"]) #男
dict = {}
dict['one'] = "This is one"
dict[2] = "This is two"
tinydict = {'name': 'runoob','code':6734, 'dept': 'sales'}
print dict['one'] # 输出键为'one' 的值 This is one
print dict[2] # 输出键为 2 的值 This is two
print tinydict # 输出完整的字典 {'name': 'runoob','code':6734, 'dept': 'sales'}
print tinydict.keys() # 输出所有键 ['dept', 'code', 'name']
print tinydict.values() # 输出所有值 ['sales', 6734, 'runoob']
3)字典的新增(写、修改)
dict["socre"] = 98
dict["班级"] = "S201"
print(dict) # {'id': 1, 'name': '张三', '性别': '男', 'socre': 98, '班级': 'S201'}
#若key是已经存在的,再次写入即修改
dict["socre"] = 90
print(dict) #{'id': 1, 'name': '张三', '性别': '男', 'socre': 90, '班级': 'S201'}
4)字典的删除(单一键值对的删除del和pop、和清空字典clear)
tinydict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
tinydict.pop('Name')
del tinydict['Name'] # 删除键是'Name'的条目
tinydict.clear() # 清空字典所有条目,只保留空字典{}
del tinydict # 删除整个字典 ,字典变量不存在了
5)字典的遍历(字典的设计初衷不是遍历,而是增删查改),哈希表能以“常数级”时间复杂度完成增删查改。注意!!Java和C++中插入元素顺序,不代表打印顺序(哈希表是无序的),python中做了特殊处理,是有序的。
for key in dict:
print(key,dict[key]) #根据key打印对应的值
print(dict.keys()) #dict_keys(['id', 'name', '性别', 'socre', '班级'])
print(dict.values()) #dict_values([1, '张三', '男', 90, 'S201'])
print(dict.items()) #dict_items([('id', 1), ('name', '张三'), ('性别', '男'), ('socre', 90), ('班级', 'S201')])
for key ,value in dict.items():
print(key,value)
6)字典中合法key的类型
使用哈希函数hash能够计算一个变量的哈希值
#可哈希的对象:(不可变对象)
print(hash(0)) #0
print(hash(3.14)) #322818021289917443
print(hash(True)) #1
print(hash("hello")) #604443049439005304
print(hash((1,2,3))) #2528502973977326415
#不可哈希:列表、字典(因为他们是可变的)
字典、列表、元组是python中常用的内置函数,相比于其他类型(int str float)他们的内部可以包含其他元素
列表是有序的对象集合,字典是无序的对象集合。字典中的元素是通过键来存取(键值对key-value),而不是通过偏移存取。
四、集合
集合 set,它是一个无序的不重复元素序列。
1)集合的创建
a = {"xiaomi","huawei","oppo","vivo"}
print(a) #
b = set() #空集合
2)添加元素
- add():添加元素
- update():可接集合,列表,元组,字典等。
b = set() #空集合
b.add("apple")
a.add("banana")
print(b)
3)合并去重:union函数或者( | 操作符)
a_set= {"apple","huawei","xiaomi"}
b_set = {"apple","oppo"}
a_set.union(b_set) #set(["apple","huawei","xiaomi","oppo"])
4)求差集\不重合度:difference、symmetric_difference找出存在集合 A 但是不存在 集合 B 的元素(- 操作符)
aset = {"Apple", "Huawei"}
bset = {"Xiaomi", "Huawei"}
aset.difference(bset) #set(['Apple'])
aset.symmetric_difference(bset) ##set(['Apple',Xiaomi])
5)集合判断
- 元素是否在集合中:in
- 两个集合是否有相同元素:isdisjoint():有相同元素返回False,没有返回True
- 是否有子集:issubset()
aset = {"Apple", "Huawei"}
print("Apple" in aset) #True
五、迭代器
可迭代对象:可以利用 for 循环的对象,如列表、元组、字典、字符串
判断是否可迭代:isinstance(),需要先导入Python 内置的collections.abc模块,其中Iterable是类
from collections.abc import Iterable
isinstance([0, 1, 2], Iterable) # 列表 True
isinstance({"name": "王炳明"}, Iterable) # 字典 True
isinstance((1,2,3), Iterable) # 元组 True
isinstance("hello", Iterable) # 字符串 True
可迭代协议:
1)第一种场景:如果一个对象内部实现了 __iter__()
方法 ,并返回一个迭代器实例,那么该对象就是可迭代对象
class Array:
mylist = [0,1,2]
def __iter__(self): # 返回迭代器类的实例
return iter(self.mylist)
my_list = Array() # 得到可迭代对象
print(isinstance(my_list, Iterable)) # True
for i in my_list:
print(i)
2)第二种场景:假设一个对象没有实现 __iter__()
,Python 解释器 __getitem__()
方法获取元素,如果可行,那么该对象也是一个可迭代对象。
from collections.abc import Iterable
class Array:
mylist = [0,1,2]
def __getitem__(self, item):
return self.mylist[item]
my_list = Array() # 得到一个可迭代对象
print(isinstance(my_list, Iterable)) # False
for i in my_list:
print(i)
什么是迭代器?
当你对一个可迭代对象使用 iter 函数后,它会返回一个迭代器对象,对于迭代器对象,我们可以使用 next 函数,去获取元素,每执行一次,获取一次,等到全部获取完毕,会抛出 StopIteration 提示无元素可取。
alist = [0, 1, 2, 3] #列表
gen = iter(alist) #对可迭代对象 列表 使用iter函数,并返回一个迭代器对象gen
next(gen) #获取迭代器中的个元素 0
next(gen) #1
next(gen) #2
next(gen) #3
next(gen) #没有对象了,抛出错误StopIteration
迭代器协议:
相比可迭代对象(list tuple dict str),迭代器内部多了一个函数_next_()
迭代器是在可迭代基础上实现的,创建一个迭代器,得先有一个可迭代对象。
如何创建一个可迭代对象?并以可迭代对象为基础创建一个迭代器?
from collections.abc import Iterator
class Array:
index = 0
mylist = [0,1,2] #可迭代对象:列表
# 返回该对象的迭代器类的实例
# 因为自己就是迭代器,所以返回self
def __iter__(self):
return self
# 当无元素时,必要抛出 StopIteration
def __next__(self):
if self.index <= len(self.mylist)-1:
value = self.mylist[self.index]
self.index += 1
return value
raise StopIteration
my_iterator = iter(Array())
print(isinstance(my_iterator, Iterator)) # output: True
print(next(my_iterator)) # output: 0
print(next(my_iterator)) # output: 1
print(next(my_iterator)) # output: 2
print(next(my_iterator)) # StopIteration
六、生成器Generator
像迭代器那样使用for循环来获取元素的函数,实现了延时计算,缓解了在大量数据下内存消耗过大的问题。当把 []
换成 ()
,返回的就不是列表了,而是一个生成器
gen = (i for i in range(5))
print(gen) #输出<generator object <genexpr> at 0x000001D0413D4F10> 表明是一个生成器对象
mylist = [i for i in range(5)]
print(mylist) #输出[0, 1, 2, 3, 4] 返回列表而非生成器
yield:相当于函数里的 return,但 又有所不同。
当一个函数运行到 yield 后,函数的运行会暂停,并且会把 yield 后的值返回出去。
若 yield 没有接任何值,则返回 None
yield 虽然返回了,但是函数并没有结束
def generator_factory(top=5):
index = 0
while index < top:
print("index 值为: " + str(index))
index = index + 1
yield index
raise StopIteration
gen = generator_factory()
print(gen)# 此时gen是生成器对象
1)生成器的使用:从生成器对象中取出元素
第一种方法:使用 next 方法一个一个地把元素取出来,如果元素全部取完了,生成器会抛出 StopIteration
的异常。
gen = (i for i in range(3))
print(gen) #输出<generator object <genexpr> at 0x000001D0413D4F10> 表明是一个生成器对象
next(gen) #0
next(gen) #1
next(gen) #2
next(gen) # 取完了报错 StopIteration
第二种方法:使用 for 循环一个一个地迭代出来
gen = (i for i in range(3))
for i in gen:
print(i)
2)生成器的激活
生成器的生命周期,有四个状态:
GEN_CREATED
:生成器已创建,还未被激活GEN_RUNNING
:解释器正在执行(只有在多线程应用中才能看到这个状态)GEN_SUSPENDED
: 在 yield 表达式处暂停GEN_CLOSED
:生成器执行结束
from inspect import getgeneratorstate
gen = (i for i in range(2))
print(getgeneratorstate(gen)) #GEN_CREATED生成器已创建,还未被激活
next(gen)
print(getgeneratorstate(gen)) #GEN_SUSPENDED 在 yield 表达式处暂停
next(gen)
print(getgeneratorstate(gen)) #GEN_SUSPENDED 在 yield 表达式处暂停
next(gen) #元素取完了,报错StopIteration
3)生成器异常:元素取完了就会抛出异常
最开始先定义一个函数
def generator_func(top=2): #定义一个生成器函数
index = 0
while index < top:
index = index + 1
yield index
raise StopIteration #没有元素返回时,抛出 StopIteration 异常,为了满足生成器的协议。
四、简单列表习题练习
(1)列表的拆分(对输入数据划分)
a = input().split() #split()函数为使用空格拆分字符串 ,
print(a)
#输入:NiuNiu NiuMei NiuNeng
#输出:['NiuNiu', 'NiuMei', 'NiuNeng']
(2)数字列表生成
输入数字字符串,将其转化为列表输出
#方法一·:
a = input().split() #分割字符串
b = [] #创建一个空列表
for i in a: #遍历输入字符串
b.append(int(i)) #将每次遍历获取到的元素添加到列表
print(b) #打印列表
#方法二:
print([int(i) for i in input().split()]) #利用列表解析快速创建列表
#-------------------------------------------------------------------------
#将输入字符串转化为列表,再在列表后添加元素
Name = input().split()
listName = []
for i in Name: #在输入中遍历
listName.append(i) #将每个字符串添加到列表
#在末尾添加元素
listName.append('Allen')
print(listName)
#在指定位置添加元素
listName.insert(0,'Allen')
print(listName)
(3)列表排序
- sorted()只是临时排序,不会改变原来的列表
- sort()会改变原来的列表,同时添加参数reverse可反转列表
my_list = ['P','y','t','h','o','n']
print(sorted(my_list)) #输出排序列表:['P', 'h', 'n', 'o', 't', 'y']
print(my_list) #输出源列表,因为sorted不改变源列表['P','y','t','h','o','n']
my_list.sort(reverse=True) #源列表反转
print(my_list) #输出原列表反转后的列表['y', 't', 'o', 'n', 'h', 'P']
(4)密码游戏:
输入一个四位数字,通过位置的交换和对应位置数字的改变,输出四位整数:
#方法一:
num = input()
b = []
for i in num:
a = int(i)
a = (a + 3) % 9 #改变数字
b.append(a)
c = b[2]*1000 + b[3]*100 + b[0]*10 + b[1] #数字交换
print('{:0>4}'.format(c)) #输出四位数字
#方法二:
num1=input()
num1=list(num1)
a=[]
for i in range(0,4):
x=str((int(num1[i])+3)%9)
a.append(x)
x=a[0]
a[0]=a[2]
a[2]=x
y=a[1]
a[1]=a[3]
a[3]=y
print(''.join(a))