本文是Python通用编程系列教程,已全部更新完成,实现的目标是从零基础开始到精通Python编程语言。本教程不是对Python的内容进行泛泛而谈,而是精细化,深入化的讲解,共5个阶段,25章内容。所以,需要有耐心的学习,才能真正有所收获。虽不涉及任何框架的使用,但是会对操作系统和网络通信进行全局的讲解,甚至会对一些开源模块和服务器进行重写。学完之后,你所收获的不仅仅是精通一门Python编程语言,而且具备快速学习其他编程语言的能力,无障碍阅读所有Python源码的能力和对计算机与网络的全面认识。对于零基础的小白来说,是入门计算机领域并精通一门编程语言的绝佳教材。对于有一定Python基础的童鞋,相信这套教程会让你的水平更上一层楼。
一 数字类型
1. 数字类型 int和float
在第一章用户交互我们给大家介绍了一下基本的数据类型,这一章主要是介绍不同数据类型的使用方法和深入研究
数字类型即变量的值,如age=18,18则是我们保存的数据。 变量的是用来反映/保持状态以及状态变化的,毫无疑问针对不同的状态就应该用不同类型的数据去标识 复制代码
数字类型只能存一个值,是不可变类型(不可变类型可以哈希,后面章节会讲解哈希)
#int整型 定义:age=10 # age=int(10) 用于标识:年龄,等级,身份证号,qq号,个数 #float浮点型 定义:salary=3.1 #salary=float(3.1) 用于标识:工资,身高,体重, 复制代码
2. int类型常用的方法
# 常用操作+内置的方法 print(bin(3)) #十进制转成二进制,0b11 print(oct(8)) #十进制转成八进制,0o10 print(10) #10 print(hex(16)) #十进制转成十六进制,0x10 复制代码
在进行用户交互程序的时候我们常用 .isdigit()这个判断用户输入是不是数字,来进行下一步操作,这样就避免了程序出错,但是需要注意的是用户输入的内容默认是字符串,判断一个字符串是否是数字,我们使用这个方法。
age = input(your age>>:) if age.isdigit(): age = int(age) age +=1 print(age) 复制代码
3. Python其他数字类型(了解)
#int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31~2**31-1,即-2147483648~2147483647 在64位系统上,整数的位数为64位,取值范围为-2**63~2**63-1,即-9223372036854775808~9223372036854775807 #long(长整型) 跟C语言不同,Python的长整数没有指定位宽,即:Python没有限制长整数数值的大小,但实际上由于机器内存有限,我们使用的长整数数值不可能无限大。 注意,自从Python2.2起,如果整数发生溢出,Python会自动将整数数据转换为长整数,所以如今在长整数数据后面不加字母L也不会导致严重后果了。 注意:在Python3里不再有long类型了,全都是int >>> a= 2**64 >>> type(a) #type()是查看数据类型的方法 <type 'long'> >>> b = 2**60 >>> type(b) <type 'int'> #complex复数型 >>> x=1-2j >>> x.imag -2.0 >>> x.real 1.0 复制代码
二 字符串类型
1. 字符串类型介绍
在python中,加了引号的字符就是字符串类型,用于标识:描述性的内容,如姓名,性别,国籍,种族,定义形式:
name='Albert' # name=str('Albert') 复制代码
字符串格式化:
name = input('请输入名字>>:') print('你好,%s' % name) 复制代码
2. 单引号,双引号和三引号的区别
#那单引号、双引号、多引号有什么区别呢? 让我大声告诉你,单双引号木有任何区别,只有下面这种情况 你需要考虑单双的配合 msg = "My name is Albert , I'm 18 years old!" #多引号什么作用呢?作用就是多行字符串必须用多引号 msg = ''' 今天我想写首小诗, 歌颂我的同桌, 你看他那乌黑的短发, 好像一只炸毛鸡。 ''' print(msg) # 三引号里面写多行内容 复制代码
3. 字符串的拼接
#数字可以进行加减乘除等运算,字符串呢?让我大声告诉你,也能?what ?是的,但只能进行"相加"和"相乘"运算。 >>> name='albert' >>> age='18' >>> name+age #相加其实就是简单拼接 'albert18' >>> name*5 'albertalbertalbertalbertalbert' #注意1: 字符串1+字符串3,并不会在字符串1的基础上加字符串2,而是申请一个全新的内存空间存入字符串1和字符串3,相当字符串1与字符串3的空间被复制了一次, #注意2:只能字符串加字符串,不能字符串加其他类型 字符串拼接(只能在字符串之间进行,且只能相加或相乘) 复制代码
字符串类型只能存一个值,是不可变类型,可以哈希。
4. 字符串类型常用的方法
(1) 按照索引取值
字符串是不可变类型,并不能改变字符串的值,取值时最多可以有三个参数,分别是起始位置,结束为止和步长,可以正向取值,反向取值(起始位置大于结束位置或者没有起始位置与结束位置,步长为-1表示从最后一个开始,步长为负数)
hobbies = "music basketball" print(hobbies[0]) print(hobbies[1]) print(hobbies[5]) print(hobbies[0:5]) print(hobbies[:5]) print(hobbies[0:5:2]) print(hobbies[0:5:-2]) print(hobbies[11:5:-2]) print(hobbies[-1]) print(hobbies[-2]) 复制代码
(2) 长度运算
print(len('name')) 复制代码
(3) 成员运算
print('a' in 'Albert') # False print('a' in not 'Albert') # True 复制代码
(4) 移除空白
print(' name'.lstrip()) # 移除左边空白 print('name '.rstrip()) # 移除右边空白 print(' name '.strip()) # 移除两边空白 复制代码
(5) 切分
print('n a me'.split(',')) print('n,a me'.split(',')) print('n,/a /me'.split('/',1)) # 数字表示切割次数,默认全部切割 print('n,a /me'.split('/')) print('a|b|c'.rsplit('|',1)) # 从右边开始切割 复制代码
(6) 组合
print('a'.join('1234')) print('a'.join('bcde')) tag = ' ' print(tag.join(['I', 'say', 'hello', 'world'])) # 可迭代对象必须都是字符串 复制代码
(7) 替换
print('abc name id'.replace('a', 'card')) name = 'albert say :i have a dream,my name is albert' # 注意此时name原来的值并没有改变,而是产生了一个替换之后新的值 print(name.replace('albert', 'Albert', 1)) 复制代码
(8) 字符串其他操作
# find,rfind,index,rindex,count name='albert say hello' print(name.find('o',1,3)) # 顾头不顾尾,找不到则返回-1不会报错,找到了则显示索引 # print(name.index('e',2,4)) # 同上,但是找不到会报错 print(name.count('e',1,3)) # 顾头不顾尾,如果不指定范围则查找所有 # center,ljust,rjust,zfill name='albert' print(name.center(30,'-')) print(name.ljust(30,'*')) print(name.rjust(30,'*')) print(name.zfill(50)) # 用0填充 # expandtabs name='albert\thello' print(name) print(name.expandtabs(1)) # captalize,swapcase,title print(name.capitalize()) # 首字母大写 print(name.swapcase()) # 大小写翻转 msg='albert say hi' print(msg.title()) # 每个单词的首字母大写 # is数字系列 # 在python3中 num1=b'4' # bytes num2=u'4' # unicode,python3中无需加u就是unicode num3='四' # 中文数字 num4='Ⅳ' #罗马数字 # isdigit:bytes,unicode print(num1.isdigit()) # True print(num2.isdigit()) # True print(num3.isdigit()) # False print(num4.isdigit()) # False # isdecimal:uncicode # bytes类型无isdecimal方法 print(num2.isdecimal()) # True print(num3.isdecimal()) # False print(num4.isdecimal()) # False # isnumberic:unicode,中文数字,罗马数字 # bytes类型无isnumberic方法 print(num2.isnumeric()) # True print(num3.isnumeric()) # True print(num4.isnumeric()) # True # 三者不能判断浮点数 num5='4.3' print(num5.isdigit()) print(num5.isdecimal()) print(num5.isnumeric()) ''' 总结: 最常用的是isdigit,可以判断bytes和unicode类型,这也是最常见的数字应用场景 如果要判断中文数字或罗马数字,则需要用到isnumeric ''' # is其他 print('===>') name='alb123ert' print(name.isalnum()) # 字符串由字母或数字组成 print(name.isalpha()) # 字符串只由字母组成 print(name.isidentifier()) print(name.islower()) print(name.isupper()) print(name.isspace()) print(name.istitle()) 复制代码
三 列表
1. 列表类型基本介绍
在[]内用逗号分隔,可以存放n个任意类型的值,用于标识:存储多个值的情况,比如一个人有多个爱好,定义格式示例:
students=['albert','james','kd',] # 或者students=list(['albert','james','kd',]) 复制代码
列表可以存储多个值,是有序的,是可变类型,不可以哈希。
2. 列表类型常用的方法
(1) 添加元素
append方法 在列表最后追加元素
l1 = ['a', 'b', 'c', 'd', ] l1.append('e') print(l1) print(l1.append('e')) # 在队尾追加,没有返回值 # ['a', 'b', 'c', 'd', 'e'] # None 复制代码
insert方法 在列表中插入元素
l1 = ['a', 'b', 'c', 'd', ] l1.insert(3,'x') # 3 指定插入索引3这个位置,就是“d”,这个位置,把‘d’ 顶到了后面 print(l1) # insert可以指定插入的位置 # ['a', 'b', 'c', 'x', 'd'] 复制代码
extend方法 在列表中同时插入多个元素,extend方法使用以及与append方法的区别 append是整体添加
l1 = [1, 2, 3, 4, 5, ] l1.append([6, 7, 8, 9, ]) # l1.append(*[6, 7, 8, 9, ]) # 会报错 print(l1) l1.extend([6, 7, 8, 9]) print(l1) 复制代码
只能接收一个参数,如果出现 打散的情况,还是会被识别成多个参数,因为程序执行执行是从左到右,从上倒下执行的,当出现 时这个列表已经被打散了,因而,会被程序识别成被传入了多个参数。
extend是逐个添加
l1 = [1, 2, 3, 4, 5, ] l1.extend([6, 7, 8, 9]) print(l1) l1.extend('abc') print(l1) l1.extend('a') # 也是可迭代对象 print(l1) # l1.extend(1) # 报错,不可迭代 print(l1) 复制代码
extend在执行添加的时候,被传入的参数必须是可迭代对象,这样通过迭代就解决了同时传入多个参数的问题,如果你还不知道可迭代对象,放心,你很快就会知道的。
(2) 删除元素
pop删除,有返回值,默认删除列表中最后一个,指定删除索引值
l1 = [1, 2, 3, 4, 5, 6, ] print(l1.pop()) # 这个是有返回值的,因为这是一个可迭代类型和我们前面的extend一类 print(l1) print(l1.pop(2)) # 2指定是列表中的索引值 print(l1) 复制代码
remove 删除 没有返回值,没有默认值,指定被删除的元素
l1 = [1, 2, 3, 4, 5, 6, ] print(l1.remove(2)) # 注意这个2 是真的2,不是索引值 # print(l1.remove()) # 报错 print(l1) 复制代码
clear 删除 保留列表名称,清空里面的值
l1 = ['a', 'b', 'c', 'd', 'e', 'b', 'c'] l1.clear() print(l1) 复制代码
del 删除 通用删除 但是一般不用
l1 = [1, 2, 3, 4, 5, 6, ] del l1[2] # 按索引 print(l1) l1 = [1, 2, 3, 4, 5, 6, ] del l1 # 在内存中删除l1 相当于没有定义l1 # print(l1) # 报错 复制代码
(3) 更改元素
注意与insert插入的不同,都是以原来的为位置为参照,insert是挤开,本质是添加,而这里是替换
l1 = [1, 2, 3, ] l1[2] = 4 print(l1) 复制代码
(4) 查找元素
按照索引或者指定列表中的元素查找
l1 = ['a', 'b', 'c', 'd', 'e', 'b', 'c'] print(l1.index('a')) print(l1.index('b',1,4)) # 两个数字分别对应起始位置和结束位置 print(l1[0:5]) # 按照索引取值和字符串的用法相同 print(l1[:5]) print(l1[0:5:2]) print(l1[:-1]) print(l1[:-2]) print(l1[5:1:-2]) 复制代码
把列表分段查找
l1 = ['a', 'b', 'c', 'd', 'e', 'b', 'c'] a = int(len(l1)/2) print(l1[:a]) # 从中间位置开始,列出前面所有的元素 print(l1[a:]) # 从中间位置开始,列出后面所有的元素 复制代码
使用enumerate对列表枚举
l1 = ['a', 'b', 'c', 'd', 'e'] for i, x in enumerate(l1, 100): # 100指定枚举开始的数字 print(i, x) 复制代码
(5) 统计长度
print(len([1,2,3,4,])) 复制代码
(6) 统计元素个数
print(['a','b'].count('a')) 复制代码
(7) 排序 reverse 反序排序
l1 = ['a', 1, 'b', 'c', 'd', 'e', 'b', 'c'] l1.reverse() print(l1) 复制代码
sort 按照ascii码来进行排序
l1 = ['a', '1', 'b', 'c', 'd', 'e', 'b', 'A', 'Z', 'c'] l1.sort() print(l1) l1.sort(reverse=True) print(l1) 复制代码
(7) 复制列表
l1 = ['a', '1', 'b', 'c', 'd', 'e', 'b', 'A', 'Z', 'c'] print(l1.copy()) 复制代码
(8) Python中的赋值,浅拷贝与深拷贝区别 赋值 对于复制的操作,最简单的就是赋值,指的是新建一个对象的引用,新建目标对象与原来的目标对象指向同一个内存地址,因而,始终保持一致。
list1 = [1, 2, 3, 4, 5, [6, 7, 8, ]] list2 = list1 list1.append(9) print(list1) print(list2) list1[5][0] = 10 print(list1) print(list2) list1[5] = 10 print(list1) print(list2) 复制代码
浅拷贝浅拷贝顾名思义就是拷贝的比较浅,我们可以把赋值认为是新建了一个对象的引用,把原来被对象内存空间的数据指向新的变量,这时同一块内存空间指向两个变量。浅拷贝与赋值不同,既然是拷贝,那么就是要开辟一块新的内存空间,复制的是原来被拷贝对象内多个元素对象的引用,有几个元素对象就赋值几个元素对象的引用。因此,被浅拷贝对象内的元素改变,会引起浅拷贝对象内元素的改变;被拷贝对象添加元素,拷贝对象不再添加元素(因为没有一个新的引用);被拷贝对象删除元素,拷贝对象也删除元素(元素都已经删了,虽然引用存在,但是并没有什么卵用)。
import copy list1 = [1, 2, 3, 4, 5, [6, 7, 8, ]] list2 = copy.copy(list1) print(list1) print(list2) list1[5].append(9) print(list1) print(list2) list1.append(6) print(list1) print(list2) list1.pop() print(list1) print(list2) 复制代码
深拷贝深拷贝其实与浅拷贝有本质的区别,它不会复制任何的引用,对象内的所有元素,子元素,孙子元素,重孙元素,曾孙元素的数据都是由复制而来。它的实现原理就是递归,只要任意元素内仍然有子元素,就会复制子元素的数据放到新的内存地址。既然这样,在使用深拷贝后,被拷贝对象的改变,不会引起拷贝对象的任何改变。
import copy list1 = [1, 2, 3, 4, 5, [6, 7, 8, ]] list2 = copy.deepcopy(list1) print(list1) print(list2) list1[5].append(9) print(list1) print(list2) list1.append(6) print(list1) print(list2) list1.pop() print(list1) print(list2) 复制代码
复制与深浅拷贝总结:
- 赋值:新建一个原来对象内存地址的引用,不开辟新的内存空间;
- 浅拷贝:新建多个原来对象内一级子元素内存地址的引用,开辟新的内存空间;
- 深拷贝:复制原来对象内的所有N级子元素的数据,开辟新的内存空间。
四 元组
与列表类型相比,非常类似只不过[]换成(),作用:用于存储多个值,对比列表来说,元组不可变(是可以当做字典的key的),不可更改,主要是用来读。
age=(11,22,33,44,55) # 本质age=tuple((11,22,33,44,55)) 复制代码
元组可以存储多个值,是有序的,是不可变类型,可以哈希。元组常用的方法,请参考列表常用方法,需要注意的是,元组只能取值,而不能改变元组的值
五 字典
1. 字典类型基本介绍
字典用于存放一个人的信息:姓名,性别,年龄,很明显是多个值,既然是存多个值,我们完全可以基于刚刚学习的列表去存放,如下:
# 既然如此,我们我们为何还要用字典? info=['albert','male',18] # 定义列表的目的不单单是为了存,还要考虑取值,如果我想取出这个人的年龄,可以用 info[2] # 但这是基于我们已经知道在第3个位置存放的是年龄的前提下,我们才知道索引2对应的是年龄,即: # # name, sex, age info=['albert','male',18] """ 而这完全只是一种假设,并没有真正意义上规定第三个位置存放的是年龄, 于是我们需要寻求一种,即可以存放多个任意类型的值,又可以硬性规定值的映射关系的类型, 比如key=value,这就用到了字典 """ 复制代码
字典用于标识存储多个值的情况,每个值都有唯一一个对应的key,可以更为方便高效地取值,字典的定义格式如下:
# 在{}内用逗号分隔,可以存放多个key:value的值,key一般是字符串,value可以是任意类型 info={'name':'albert','age':18,'sex':18} # info=dict({'name':'albert','age':18,'sex':18}) 复制代码
字典可以存储多个值,是无序的,是可变类型,不可哈希。
2. 字典类型常用的方法
(1) 增加元素
通过键值对的方式
l1 = { 'name': 'albert', 'age': 18, 'gender': 'male' } l1['hobbies'] = "music" print(l1) 复制代码
用fromkeys构造一个字典
""" 第一个参数迭代循环的字典的key,第二个参数表示value, 可以多个key循环对应这个value,也可以只有一个key,也可以没有value """ a = l1.fromkeys(l1,'I am Albert') print(a) b = dict.fromkeys('name') # 必须有一个可迭代类型,作为字典的key print(b) b = dict.fromkeys('e') # 也可以迭代 print(b) # b = dict.fromkeys(1) #报错 数字类型不可迭代 b = dict.fromkeys([1,2,3,]) print(b) 复制代码
(2) 删除元素
del 通过字典的key删除
l1 = { 'name': 'albert', 'age': 18, 'gender': 'male' } del l1['name'] print(l1) 复制代码
pop 或者popitem删除
l1 = { 'name': 'albert', 'age': 18, 'gender': 'male' } res = l1.pop('name') # 删除指定key的value,并拿到一个返回值 print(res) print(l1) res2 = l1.popitem() # 随机返回并删除字典中的一对键和值(一般删除末尾对)。 # 如果字典已经为空,却调用了此方法,就报出KeyError异常。 print(res2) print(l1) 复制代码
(3) 更改元素
通过键值对的方式
l1 = { 'name': 'albert', 'age': 18, 'gender': 'male','3':3, } l1['name'] = '马一特' print(l1) 复制代码
通过setdefault 或者update操作,两者使用和区别如下: setdefault只添加不修改
d1 = { 'name': 'albert', 'age': 18, } d1.setdefault('name', 'Albert') d1.setdefault('gender', 'male') print(d1) 复制代码
update既添加也修改
d1 = { 'name': 'albert', 'age': 18, } d1.update({'name': 'Albert', 'gender': 'male'}) # 注意传参方式的不同 print(d1) 复制代码
(4) 查找元素
通过键值对查找
l1 = { 'name': 'albert', 'age': 18, 'gender': 'male' } a = l1['name'] print(a) 复制代码
通过get方法查找
l1 = { 'name': 'albert', 'age': 18, 'gender': 'male' } a = l1.get('hobbies') # 找不到不报错 print(a) 复制代码
通过enumerate 枚举
d1 = { 'name': 'albert', 'age': 18, 'gender': 'male', '3':3, } for a in enumerate(d1): print(a) 复制代码
通过.keys(),.values(),.items()等方法
d1 = { 'name': 'albert', 'age': 18, 'gender': 'male', '3':3, } a = d1.keys() print(a) print(list(a)[0]) a = d1.values() print(a) print(list(a)[0]) a = d1.items() print(a) print(list(a)[0]) 复制代码
通过for循环遍历
d1 = { 'name': 'albert', 'age': 18, 'gender': 'male', '3':3, } for k,v in d1.items(): print(k,v) 复制代码
(5) 成员运算与长度运算
参考列表的运算方法,成员运算的依据是字典的key,而不是value,长度运算都可以作为参考的依据
六 集合类型
花括号内,多个元素用逗号分割,用来存储多个值,并且是无序的,那么这多个值不能用来取值,但是我们可以使用它来进行去重和关系运算。
# 集合的元素遵循三个原则: 1: 每个元素必须是不可变类型(可作为字典的key) 2: 没有重复的元素 3: 无序 # 注意集合的目的是将不同的值存放到一起,不同的集合间用来做关系运算,无需纠结于集合中单个值 复制代码
集合类型可以存多个值,是无序的,是可变类型,不可以哈希。
关系运算练习
有如下两个集合,piano是报名钢琴课程的学员名字集合,violin是报名小提琴课程的学员名字集合 piano={'albert','孙悟空','周星驰','朱茵','林志玲'} violin={'猪八戒','郭德纲','林忆莲','周星驰'} 1. 求出即报名钢琴又报名小提琴课程的学员名字集合 2. 求出所有报名的学生名字集合 3. 求出只报名钢琴课程的学员名字 4. 求出没有同时这两门课程的学员名字集合 复制代码
参考答案
# 求出即报名钢琴又报名小提琴课程的学员名字集合 print(piano & violin) # 求出所有报名的学生名字集合 print(piano | violin) # 求出只报名钢琴课程的学员名字 print(piano - violin) # 求出没有同时这两门课程的学员名字集合 print(piano ^ violin) 复制代码
七 布尔类型
计算机俗称电脑,即我们编写程序让计算机运行时,应该是让计算机无限接近人脑,或者说人脑能干什么,计算机就应该能干什么,人脑的主要作用是数据运行与逻辑运算,此处的布尔类型就模拟人的逻辑运行,即判断一个条件成立时,用True标识,不成立则用False标识。
#布尔值,一个True一个False >>> a=3 >>> b=5 >>> a > b #不成立就是False,即假 False >>> a < b #成立就是True, 即真 True # 接下来就可以根据条件结果来干不同的事情了: if a > b: print(a is bigger than b ) else: print(a is smaller than b ) # 上面是伪代码,但意味着,计算机已经可以像人脑一样根据判断结果不同,来执行不同的动作。 复制代码
布尔类型的重点知识
#所有数据类型都自带布尔值 1、None,0,空(空字符串,空列表,空字典等)三种情况下布尔值为False 2、其余均为真 复制代码
可变类型与不可变类型(重点)
# 1.可变类型:在id不变的情况下,value可以变,则称为可变类型,如列表,字典 # 2. 不可变类型:value一旦改变,id也改变,则称为不可变类型(id变,意味着创建了新的内存空间) 复制代码
八 collections容器数据类型
1. namedtuple 命名元组
from collections import namedtuple # 创建一个命名元组对象 point = namedtuple('p', ['x', 'y']) # p代表名称,"x"和"y"为内容 p = point(1, 2) print(p) print(p.x) # 1 print(p.y) # 2 复制代码
2. deque 超级列表
from collections import deque # 类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop) d = deque('abcd') for i in d: print(i) print(d[0]) print(d[1]) d.append('e') # 从右边加入 print(d) d.appendleft('x') # 从左边加入 print(d) d.pop() # 从右侧弹出 print(d) d.popleft() # 从左侧弹出 print(d) deque(reversed(d)) # 反转顺序 print(d) # d = list(d) # 转化成list # d = list(reversed(d)) # print(d) d.extend('xyz') # 从右侧添加 print(d) d.extendleft('nba') # 从左侧添加 print(d) d.rotate(1) # 把最右边的元素挪到最左边 print(d) d.rotate(-1) # 把最左边的元素挪到最右边 print(d) d.clear() # 清空 # d.pop() # 报错 复制代码
3. ChainMap 链映射
from collections import ChainMap """ 一个 ChainMap 类是为了将多个映射快速的链接到一起,这样它们就可以作为一个单元处理。 它通常比创建一个新字典和多次调用 update() 要快很多。 这个类可以用于模拟嵌套作用域,并且在模版化的时候比较有用。 """ # 链映射的用法 dict1 = {'name': 'Albert', 'age': 18} dict2 = {'weight': 65, 'height': 180} res = list(ChainMap(dict1, dict2)) print(res) 复制代码
4. Counter 计数字典
from collections import Counter # 计数 cnt = Counter() for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']: cnt[word] += 1 print(cnt) # Counter({'blue': 3, 'red': 2, 'green': 1}) # 数学运算 c = Counter(a=3, b=1) d = Counter(a=1, b=2) print(c + d) # 相同的部分相加 # Counter({'a': 4, 'b': 3}) print(c - d) # 相同的部分相减 # Counter({'a': 2}) print(c & d) # 相同的部分取最小 # Counter({'a': 1, 'b': 1}) print(c | d) # 相同的部分取最大 # Counter({'a': 3, 'b': 2}) 复制代码
Collections容器类型一共有9种,除了上面介绍的4种之外还有OrderedDict,defaultdict,UserDict,UserList,UserString,他们的用法不是完全相同,但是使用起来并不复杂。