求职时找Java开发岗,offer上给的中间件开发岗,然后入职当天老大让我跟着搞python,没办法,只能捡一捡python了。
前言
如果无编程基础,建议还是直接找视频刷一刷再看文档,如果有编程基础,就直接撸官方文档就行,不过在这里给大家推荐一本书:《A byte of Python》链接:[https://python.swaroopch.com],如果对英文阅读有困难的话,找找里边的其他语言版本,都可以看看的,不过还是推荐英文版,中文版的看了一点,总感觉没那味~
对于IDE来说,用啥都行,配合pylint把得分拉满,可能前期很痛苦,但是对于以后的编码习惯有很大的帮助。我用的是pycharm,装个pylint插件就OK
对于web开发来说,有了python基础和web开发基础,flask和Django找官方文档照着撸一遍就OK
这篇文章没按顺序来,想真正从 0 开始学python,建议移步到文章最后的 总体略叙 。
废话少说,直接开撸
列表
列表特点:
有序集合:数字、文字都可用列表来实现,只需按序排列即可
具有索引值:只要通过索引值就能获取某个元素的值,也支持切片运算
列表长度不受限:列表对象同样以len()函数获取长度,长度可长可短。当列表中有列表形成嵌套时,可根据需求设置长短不一的列表对象
属于“可变序列”:元组属于不可变序列类型,列表可变,可用append()等方法对列表元素进行操作
列表的创建:(列表中含有列表成为矩阵)
data = [] #创建一个空列表
data1 = [1,2,3,4,4] #存储数值的list对象
data2 = ['one', 34, '小弘'] #含有不同类型的列表
data3 = ['mary', [56, 78], 'hello', [34, 89]] #创建一个矩阵
列表元素的获取与删除:(列表特性可变,可用[]运算符指定索引编号来更改某个元素值,也可用del删除某个列表中的元素,也支持切片)
例:
data = [11, 33, 'xiaohong', 'helloword', 44]
data[-1] = 66
print(data)
输出结果:[11, 33, 'xiaohong', 'helloword', 66]
del(data[0])
print(data)
输出结果:[33, 'xiaohong', 'helloword', 66]
del(data[:])
print(data)
输出结果:[]
列表有关的方法:
append():将元素添加在列表的最后
例:
data = [1,2,3,4,'hello']
data.append('world')
print(data)
输出结果:[1, 2, 3, 4, 'hello', 'world']
extend():将可迭代对象添加在列表的最后,不可直接添加元素,添加的对象必须是有序的对象(可迭代的)
例:
data1 = [11,2,3,44]
data2 = ['xiaohong', 'hello']
data2.extend(data1)
print(data2)
输出结果:['xiaohong', 'hello', 11, 2, 3, 44]
insert(i, x):将元素x按指定的索引编号i插入到列表中
例:
data = [1,2,3,4,'hello',5,6]
data.insert(5,'world')
print(data)
输出结果:[1, 2, 3, 4, 'hello', 'world', 5, 6]
remove():将指定元素从列表中删除,与del list[x]相同
例:
data = [1,2,3,4,'hello',5,6]
data.remove('hello')
print(data
输出结果:[1, 2, 3, 4, 5, 6]
pop([i]):按索引值i来删除一个元素并返回,当未给定索引值时会删除最后一个元素并返回
例:
data = [1,2,3,4,'hello',5,6]
data.pop(4)
print(data)
输出结果:[1, 2, 3, 4, 5, 6]
data.pop()
print(data)
输出结果:[1, 2, 3, 4, 5]
s[i] = x :将指定元素x按索引编号i重新赋值
例:
data = [1,2,3,4,'hello',5,6]
data[4] = 'xiaohong'
print(data)
输出结果:[1, 2, 3, 4, 'xiaohong', 5, 6]
clear():清除列表中所有元素,与del s[:]相同
例:
data = [1,2,3,4,'hello',5,6]
data.clear()
print(data)
输出结果:[]
reverse():将序列的元素全部反转
例:
data = [1,2,3,4,'hello',5,6]
data.reverse()
print(data)
输出结果:[6, 5, 'hello', 4, 3, 2, 1]
count():计算序列中某元素出现的次数
例:
data = [1,2,3,4,'hello',5,6,1]
print(data.count(1))
输出结果:2
index():序列中某元素第一次出现的索引值
例:
data = [1,2,3,4,'hello',5,6,1]
print(data.index(3))
输出结果:2
列表的数据排序:
sort()方法:(不可排序不同类型的数据)
语法:List.sort(key, reverse = None)
参数解释:key:默认值是None,可指定项目进行排序,参数可省略
reverse:默认None是升序排序;若reverse = True,则为降序排序
例:
data = ['hello', 'world', 'tom', 'Jerry']
data.sort() #默认是升序排序
print(data)
输出结果:['Jerry', 'hello', 'tom', 'world']
number = [1, 2, 0, 9, 5, 7]
number.sort(reverse=True) #降序排序
print(number)
输出结果:[9, 7, 5, 2, 1, 0]
列表sort()方法与元组sorted()方法的区别:
list的sort()方法可直接对同数据类型的列表数据进行排序并返回一个新的列表
tuple的sorted()方法进行排序后返回一个新的排序后的列表,而原元组元素顺序并不改变,tuple不可使用sort()方法
内置函数sum():
语法:sum(iterable[, start])
参数说明:iterable:表示可迭代的序列数据
start:指定想要累加元素的索引编号,省略时表示索引从0开始
例:
number = [1, 2, 0, 9, 5, 7]
print(sum(number))
输出结果:24
列表推导式:(推导式:将一个或多个迭代器聚集在一起,在用for循环作为条件测试)
语法:[表达式 for item in 可迭代的]
[表达式 for item in 可迭代的 if表达式]
解释说明:列表推导式要用[]存放新列表的元素
使用for/in循环读取可迭代对象
简单语法使用说明:
aList = [] #空的列表,先创建一个空列表aList
for item in 可迭代的: #用for循环读取列表或可迭代的对象
if 条件表达式: #再以if语句作为条件表达式
aList.append(item) #条件表达式符合者(True)用append()方法将item加入列表中
使用推导式原因:提高性能,让for循环更加自动化
例:
#找出10-50之间能被7整除的数值增加到列表中
num = [1, 2, 3, 4]
for item in range(10, 50):
if (item %7 == 0):
num.append(item)
print('增加10-50间能被7整除的整数之后的num列表是:', num)
输出结果:增加10-50间能被7整除的整数之后的num列表是: [1, 2, 3, 4, 14, 21, 28, 35, 42, 49]
两个列表用列表推导式进行合并:(双重for循环)
例1:
wd1 = ['2019'] #List - year
wd2 = ['jan', 'feb', 'mar'] #Lsit - Month
#Lsit Comprehensions
#使用列表推导式,表达式y,m以元组进行处理,再以for循环读取这两个列表对象;Unpacking的作用,所以输出 ('2019', 'jan')...
print('List Comprehensions\n', [(y, m) for y in wd1 for m in wd2])
#double for/in
combin = [] #List
#第一个for循环读取第一个列表,第二个for循环读取第二个列表,在用append()方法加入,就会输出元组组成形式(y,m)
for y in wd1:
for m in wd2:
combin.append((y, m))
print('双重for/in读取:\n', combin)
输出结果: List Comprehensions
[('2019', 'jan'), ('2019', 'feb'), ('2019', 'mar')]
双重for/in读取:
[('2019', 'jan'), ('2019', 'feb'), ('2019', 'mar')]
例2:使用列表推导式将两个列表的字符串进行串接
num = ['AB01', 'AB425', 'CH004', 'CK4131', 'DD0048', 'Dy00231']
room = ['A', 'B', 'C']
rooms = [r + '-' + n for r in room for n in num if r[0] == n[0]]
print(rooms)
输出结果:['A-AB01', 'A-AB425', 'C-CH004', 'C-CK4131']
39.二维列表:又称矩阵、多维列表、嵌套列表
矩阵语法:num = [[11, 12, 13], [22, 24, 26], [33, 35, 37]]
解释说明:表示num是一个列表
num[0](或称第一行索引)存放另一个列表;num[1](或称第二行索引)也是存放另一个列表,以此类推
第一行索引有三列,分别存放元素,其位置num[0][0]指向数值[11],num[0][1]指向数值[12],以此类推
num是一个3*3的二维列表,其行和列的索引(或称为下标)如下:
列索引[0] 列索引[1] 列索引[2]
行索引[0] 11 12 13
行索引[1] 22 24 26
行索引[2] 33 35 37
存取元素语法:列表名称[行索引][列索引]
例:
>>> num = [[11, 12, 13], [22, 24, 26], [33, 35, 37]]
>>> num[0]
[11, 12, 13]
>>> num[0][2]
13
>>> num[0][2] = 99
>>> num[0][2]
99
二维列表的读取:使用双重for循环
例:
num = [[11, 12, 13], [22, 24, 26], [33, 35, 37]]
for index in num:
print()
for item in index:
print(item, end = ' ')
输出结果:
11 12 13
22 24 26
33 35 37
40.矩阵与列表推导式:当列表是不规则列表,或者要改变列表的读取方式时需要创建嵌套列表推导式
一维列表举例:
#一维列表使用列表推导式搭配range()函数可以输出某个区间的数值
print([x for x in range(1, 6)])
输出结果:[1, 2, 3, 4, 5]
有变化的二维列表举例:(嵌套列表推导式):
print([ [y for y in range(1, x+1)] for x in range(1, 5)])
输出结果:[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
主例:
matr = [#3*4二维List
[11, 12, 13, 14],
[22, 24, 26, 28],
[33, 35, 37, 29]]
#双重for读取matr
print('一般嵌套for')
for one in matr: #第一重for循环
for two in one: #第二重for循环
print(two, end = ' ')
print()
#List Comprehensions
print('以行为主')
print('\n'.join(['{}'.format(one) for one in matr]))
#先读行索引,11,22,33
print('行、列交换')
print('\n'.join([''.join(['{0:3d}'.format(row[item]) for row in matr]) for item in range(4)]))
输出结果:
一般嵌套for
11 12 13 14
22 24 26 28
33 35 37 29
以行为主
[11, 12, 13, 14]
[22, 24, 26, 28]
[33, 35, 37, 29]
行、列交换
11 22 33
12 24 35
13 26 37
14 28 29
例2:打印99乘法表:
for i in range(1,10):
for j in range(1, i+1):
print('%s*%s=%s' %(i, j, i*j), end =' ')
print()
输出结果:
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
使用双层列表推导式打印99乘法表:
for i in range(1, 10):
print(" ".join(["%d*%d=%d" % (j, i, i * j) for j in range(1, i + 1)]))
输出结果:
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
42.不规则列表:
内置函数isinstance():判断对象是否是该类型,如果是返回True,否则返回False
语法:isinstance(object, classinfo)
说明:oject:要判别的对象的名称,配合classinfo参数所指定的对象,如果符合就返回布尔值True
classinfo:指明判别的对象
例:
student = ['mary', '小明']
print(isinstance(student, list))
输出结果:True
例2:
#统计成绩
student = ['Tomas', [78, 96, 92], 'Marry', [77, 61, 54], 'Graham', [64, 82, 79]]
print('%8s %s %2s %2s %3s %3s' %('Nanme', '语文', '英语', '数学', '总分', '平均'))
for outer in student: #第一重for循环
#判断outer读进来的事元素还是列表
if isinstance(outer, list):
for inner in outer: #第二重循环
print('%5d'%(inner), end = '')
print('%5d %6.2f'%(sum(outer), sum(outer)/3), end = '')
print() #换行
else: #非空表直接输出其元素
print('%7s:'%(outer), end = '')
else:
print('分数计算完毕')
输出结果:
Nanme 语文 英语 数学 总分 平均
Tomas: 78 96 92 266 88.67
Marry: 77 61 54 192 64.00
Graham: 64 82 79 225 75.00
分数计算完毕
43.列表与复制
python的复制分类:
浅复制(Shallow copy):只复制对象引用,不复制对象本身
深复制(Deep copy):要调用copy模块的deepcopy方法来复制
列表的浅复制:
例:
>>> data = [1, 2, 3, 4] #表示data是一个对象引用,它指向以连串的数值
>>> num = data #表示对象引用data、num,它们同时指向一个列表对象
>>> num,data
([1, 2, 3, 4], [1, 2, 3, 4])
>>> num[0] = 99
>>> num,data #如果对data或者num中的元素作修改,这两个对象都会同时反映这种修改
([99, 2, 3, 4], [99, 2, 3, 4])
注:若序列类型存储的数据非常庞大,通过“=”运算符将另一个对象引用同时指向同一个对象可以降低对系统的负荷
实现浅复制的方法:
使用*运算符,执行运算时,意味着新列表中每个索引位置都会引用旧列表中每个索引位置的元素
例:
>>> x = [23, 56]
>>> y = x*3
>>> y
[23, 56, 23, 56, 23, 56]
使用切片运算:不会复制元素,而是创建一个新列表,再把原列表的每个元素指定给新列表的索引,以便进行引用
例:
>>> #列表中含有列表
>>> list = [[3, 2, 1], [22, 24, 47], [11, 25, 51]]
>>> x = list[0:2]
>>> x
[[3, 2, 1], [22, 24, 47]]
>>> list
[[3, 2, 1], [22, 24, 47], [11, 25, 51]]
>>> x[0][1] = 99
>>> list; x
[[3, 99, 1], [22, 24, 47], [11, 25, 51]]
[[3, 99, 1], [22, 24, 47]]
使用序列类型提供的copy方法,等同于切片运算的[:]
例:
>>> x = [11, [13, 15], [22, 24, 26]]
>>> y = x[:]
>>> y
[11, [13, 15], [22, 24, 26]]
>>> z = x.copy() #List的copy()方法
>>> z
[11, [13, 15], [22, 24, 26]]
copy模块的copy()方法:导入copy模块进行复制。copy()方法用来实施浅复制,deepcopy()方法用来深复制
语法:copy.copy(x)
copy.deepcopy(x) #x是想要复制的对象
例:
import copy
data1 = [11, 22]
data2 = copy.copy(data1)
print(data1, data2)
data1[0] = 99 #修改data1的值不会影响data2
print(data1, data2)
输出结果:[11, 22] [11, 22]
[99, 22] [11, 22]
注:当copy模块的copy()方法想要复制的对象是一个列表中含有列表的对象引用时,会以浅复制处理
例:
>>> import copy
>>> #列表中含有列表
>>> num1 = [11, [22, 23], 31, 34, 35]
>>> num2 = copy.copy(num1)
>>> num1;num2
[11, [22, 23], 31, 34, 35]
[11, [22, 23], 31, 34, 35]
>>> num1 == num2
True
>>> num1[0] = 99 #num[0]是对象,修改后只影响自己,num2不影响
>>> num1;num2
[99, [22, 23], 31, 34, 35]
[11, [22, 23], 31, 34, 35]
>>> num2[1][1] = 88 #num2[1][1]是对象引用,修改后均影响
>>> num1;num2
[99, [22, 88], 31, 34, 35]
[11, [22, 88], 31, 34, 35]
注:使用copy模块的copy()方法时:
一般对象,copy()方法会复制对象引用·
对象引用使用copy()方法时,对象本身不会被复制
deepcopy()方法复制对象本身:当要复制的是对象本身,而它又是一个列表中含有列表的对象时,就必须使用deepcopy()方法
例:
>>> import copy
>>> #列表中含有列表
>>> num1 = [11, [22, 23], 31, 34, 35]
>>> num3 = copy.deepcopy(num1)
>>> num1;num3
[99, [22, 88], 31, 34, 35]
[99, [22, 88], 31, 34, 35]
>>> num3[-1] = 96
>>> num1;num3
[99, [22, 88], 31, 34, 35]
[99, [22, 88], 31, 34, 96]
>>> num1[1][0] = 66
>>> num1;num3
[99, [66, 88], 31, 34, 35]
[99, [22, 88], 31, 34, 96]
使用深度复制时,num1和num3都是独立的对象引用,所以不管是改变对象还是改变对象引用都只会影响原有的列表对象
元组
元组:元组元素既有顺序性,不可随意变更顺序创建元组用()来存放元素,当只有一个元素时,用 , 来区分是元组元素还是数值,例(1,);元组可无括号;元组可存放不同数据类型
注:>>> tuple = (15,)
>>> tuple1 = (15)
>>> type(tuple)
<class 'tuple'>
>>> type(tuple1)
<class 'int'>
元组创建语法:tuple = () #创建一个空元组
tuple1 = (1,) #创建只含有一个元素的元组
tuple2 = (1,2,3) #创建含有多个元素的元组
('小弘','Judy',123) #创建一个没有名称的元组
data = ('小弘','Judy',123) #创建一个给予名称的元组
data = '小弘', 'Judy',123 #创建一个无括号的元组
元组是不可变动的对象,即元组已经创建就不可变更每个索引所指向的引用对象,如果通过索引编号来改变其值会报错
改变元组元素的值的方法:使用+或*
+:将两个元租对象串接成一个
例:
>>> tuple1 = (11,22,'xiaoming','hello')
>>> tuple2 = ('world', 33,44)
>>> tuple1 +tuple2
(11, 22, 'xiaoming', 'hello', 'world', 33, 44)
*:把元组的元素复制成多个
例:
>>> tuple3 = 'hello', 'world' *3
>>> tuple3
('hello', 'worldworldworld')
>>> tuple3 = ('hello', 'world')*3
>>> tuple3
('hello', 'world', 'hello', 'world', 'hello', 'world')
count()方法:统计某元素出现的次数
例:
>>> tuple1 = (1,2,3,1,2,3,1,4,5,6,6)
>>> tuple1.count(1)
3
>>> tuple1.count(6)
2
index()方法:获取某元素第一次出现的索引编号
例:
>>> tuple1 = (1,2,3,1,2,3,1,4,5,6,6)
>>> tuple1.index(3)
2
index()方法扩展:
index(x, [i, [j]])
x:元组对象的元素,不可少
i、j:选择参数,从i开头索引,到j为结束结束索引
例:
>>> data = 25, 17, 45, 6, 17 #创建元组
>>> print(data.index(17)) #17的第一次出现的索引
1
>>> print('第二个17', data.index(17,2)) #第2次出现17的索引值
第二个17 4
>>> print('data[0:4].index(45)--', data[0:4].index(45)) #另一种方式使用index()函数
data[0:4].index(45)-- 2
>>> print(data.index(17, 0, 2)) #对索引值为[0 : 2]范围内的值进行检索查找17出现的位置
1
>>> print(data.index(17, 2, 4)) #对索引值为[2 : 4]范围内的值进行检索查找17出现的位置,没有则报错
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
print(data.index(17, 2, 4))
ValueError: tuple.index(x): x not in tuple
元组元素的读取:
for/in来读取元组元素:
例:
tuple = (11,21,32,42)
for item in tuple:
print(item, end=' ')
输出结果:11 21 32 42
tuple = (11,22,3,3,4,5)
for item in range(len(tuple)):
print('%d %d' %(item, tuple[item]))
输出结果: 0 11
1 22
2 3
3 3
4 4
5 5
while读取元组元素:
例:
tuple = (11,22,33,44,55)
item = 0
while item < len(tuple):
print(tuple[item], end = ' ')
item += 1
else:
print('读取完毕')
输出结果:11 22 33 44 55 读取完毕
元组的相关操作:
元素的快速拆分:Unpacking,可用于List 和 Tuple
例:
word = 'ABC'
#将字符串派分给三个变量
one, two, three = word
print(one, two, three, end = ' ')
输出结果:A B C
例2:
student = [['小明', 55, 68, 74], ['小弘', 66, 76, 57], ['小兰', 56, 78, 45]] #创建一个矩阵(列表中有列表)
for (name, math, english, computer) in student:
print('%6s'%name, '总分:', (math + english + computer))
输出结果:
小明 总分: 197
小弘 总分: 199
小兰 总分: 179
元组切片:同字符串,但使用负值索引编号时必须从左向右设置,否则无法取出元素
元组排序:
sorted()方法:sorted()方法返回一个新的列表List,所以排序后并不改变原有元组的元素顺序
语法:sorted(iterable[, key][, reverse])
iterable:可迭代的对象,参数不能省略
key:默认值None,可指定项目进行排序,选择性参数
reverse:选择性参数,默认值False为升序。若reverse = True,则以降序进行排序
例:
data = 258, 12, 37, 69, 47 #创建元组
print('原元组内容:', data)
print('默认排序为升序,从小到大排序:', sorted(data))
print('从大到小排序:', sorted(data, reverse=True))
print('排序后的元组元素位置变化:', data)
输出结果:
原元组内容: (258, 12, 37, 69, 47)
默认排序为升序,从小到大排序: [12, 37, 47, 69, 258]
从大到小排序: [258, 69, 47, 37, 12]
排序后的元组元素位置变化: (258, 12, 37, 69, 47)
字典
44.字典:字典来自映射类型,属于无需集合。
映射类型:有序映射类型:来自标准函数库的collections.OrderedDict,由于是dict的子类,所以拥有和字典一样的属性和方法
无序映射类型:字典是标准映射类型中唯一内置的对象。另一个也是来自标准函数库的collections.defaultdict,同样是dict的子类
映射类型本身属于可变对象,支持迭代器,所以内置函数len()和成员运算符in都能使用
映射类型的特点:
无序的任意类型:相对于序列类型的顺序性,存储于字典的数据则很随性。由于是可变容器,因此可以存储任意类型的对象
使用键(key)来获取值(value):字典由键和值来组成 键/值 对(key-value pairs)。也就是字典的key如同序列对象的索引,通过key可以找到配对的值
支持嵌套:字典里可包含序列类型的任意一种,根据实际需求改变其长度
以哈希表为基底,可以快速检索
使用 == 和 != 运算符将字典逐项目进行对比,其他的比较运算符则不能使用
使用字典的注意事项:
键不具顺序,为不可改变对象,只能是可哈希的(Hashable)
键能使用的类型有:整数或浮点数、字符串或元组(Tuple)、不可变集合(frozenset)
字典列举时,字符串(str)和整数(int)较通用
键无法实用的数据类型有:字典(dict)、列表(list)、和集合(set)不能作为字典的键
由于键不具有索引,所以不能进行切片运算
创建字典的方法:
使用 {} 来创建字典:(除了空字典外,创建的字典由于不具有顺序性,因此输出元素时可能会和创建时不相同)
语法:{key1 : value1, key2 : value2, key3 : value3, ...}
例:
data = {} #创建一个空的字典
score = {'John': 86, 'Mary': 99}
print(data)
print(score)
输出结果: {}
{'John': 86, 'Mary': 99}
使用内置函数dict()函数:以关键字参数作为参数,或者加入zip()函数来创建字典
语法:dict(**kwarg) dict(mapping, **kwarg) dict(iterable, **kwarg)
说明:kwarg:表示关键字参数 mapping:映射对象 iterable:可迭代的
例:
dict()函数配合关键字参数,以“变量 = 值”来产生项目,变量成为字典的key,值成为字典的value
dct1 = dict(John = 87, Eric = 75, Judy = 91, Tomas = 65)
print(dct1)
输出结果:{'John': 87, 'Eric': 75, 'Judy': 91, 'Tomas': 65}
dict()函数以迭代器参数,表示要以[] 或 ()来表示它的对象是列表(List)或元组(Tuple)
dct2 = dict([('year', 1998), ('month', 5), ('day', 27)])
print(dct2)
dct3 = dict([['name', 'Marry'], ['sex', 'female']])
print(dct3)
输出结果: {'year': 1998, 'month': 5, 'day': 27}
{'name': 'Marry', 'sex': 'female'}
dict()函数配合zip()函数,将迭代器组成新的字典
zip()函数语法:zip(iter1, [,iter2 [...]]);以可迭代的为元素来产生迭代器,先指定key再配对value,他们分别放在元组中
dct4 = dict(zip(['Sunday', 'Monday', 'Tuesday'], ['周日', '周一', '周二']))
print(dct4)
输出结果:{'Sunday': '周日', 'Monday': '周一', 'Tuesday': '周二'}
使用列表或者元组来产生一键对多值的效果:
dct5 = {'A01':["Mary", 65, 78], 'A02':('上海', 'beijing')}
print(dct5)
输出结果:{'A01': ['Mary', 65, 78], 'A02': ('上海', 'beijing')}
#读取字典的项目 使用for循环读取时,key加上[]运算符就会返回对应的value
data = {1:'one', 2:'two', 3:'three'}
for key in data:
print('key = %2d, value = %4s'%(key, data[key]))
输出结果: key = 1, value = one
key = 2, value = two
key = 3, value = three
先创建空字典,再通过[]运算符以键设值
例:
>>> data = {}
>>> data['one'] = 1
>>> data['two'] = 2
>>> data
{'one': 1, 'two': 2}
内置函数locals():通常内置函数locals()并无参数,它会检查当前有效范围的局部变量,并以字典形式返回,变量名会变成字典的key,变量值则是字典的value
例:
>>> name = 'Mary'; score = 196; tall = '165cm'
>>> print(locals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'data': {'one': 1, 'two': 2}, 'name': 'Mary', 'score': 196, 'tall': '165cm'}
注:使用locals()函数的特性输出字典项目时,可以配合format()方法或格式运算符,将映像类型通过拆分 ** 运算传递键值项目
例:
>>> cond = 'Looping'
>>> name = 'Dictionary'
>>> 'When {cond} through {name}'.format(**locals())
'When Looping through Dictionary'
键、值的操作
del d[key] 删除字典项目,由key指定
key in d 判断键key是否在字典中
key not in d 判断键key是否不在字典中
iter(dictview) 由字典的key所创建的迭代器
d.keys() 以元组类型返回字典的键
d.values() 以元组类型返回字典的值
d.items() 以元组类型返回字典的“键/值”组
字典元素的添加和修改:
[]运算符不仅可以存取字典的项目,还可以添加字典的项目
语法:d[key] #返回key对应的值(value)
d[key] = value #添加或重新将key、value配对
例:
score = {'Chinese':99, 'math':98}
print(score['Chinese']) #[]运算符通过键对字典项目的值进行获取
输出结果:99
#无key时报错
print(score['English'])
Traceback (most recent call last):
File "E:/PythonTest/venv/Include/ScoreTest.py", line 1006, in <module>
print(score['English'])
KeyError: 'English'
score['math'] = 100
print(score['math']) #[]运算符进行字典项目的更改
输出结果:100
score['English'] = 66 #使用[]运算符进行对字典项目的的添加
print(score)
输出结果:{'Chinese': 99, 'math': 100, 'English': 66}
iter()函数:产生key的迭代器
例:
score = {'Chinese':99, 'math':98}
print(list(iter(score)))
输出结果:['Chinese', 'math']
如何防止找不到key:
使用成员运算符in/not in进行检查
使用get()方法,无key时会以None响应
使用setdefault()方法,无key时会添加此key,而对应的值则以None响应
类方法:fromkeys():字典类提供的方法,先创建字典的key,再以[]运算符填入字典的value
语法:fromkeys(seq[, value])
说明:seq:序列类型
value:值,选择参数,如果设置该参数,就会分派给参数seq
例:
#设置value
dt = {}.fromkeys('ABC', 123)
print(dt)
输出结果:{'A': 123, 'B': 123, 'C': 123}
#省略value
dt = {}.fromkeys('ABC')
print(dt)
输出结果:{'A': None, 'B': None, 'C': None}
字典相关方法:
d.get(key, default) 返回key对应的值,若无此键,则以参数default默认值None返回
d.setdefault(key, default) 若key不存在,添加键,值则以None回应
d.pop(key, default) 按照键所对应的值进行删除,若无此键,则返回default
d.update(other) 以other提供的键值来更新字典
d.clear() 清除字典所有的内容
d.copy() 以浅复制创建字典对象
get()方法预防找不到key:
dt = {1:'ONE', 2:'two', 3:'three'}
print(dt.get(1))
print(dt.get(4))
print(dt.get(5, '暂无此值'))
输出结果:
ONE
None
暂无此值
update()方法合并两个字典:
dt = {1:'ONE', 2:'two', 3:'three'}
dt2 = {4:'four', 5:'five'}
dt.update(dt2)
print(dt)
输出结果:{1: 'ONE', 2: 'two', 3: 'three', 4: 'four', 5: 'five'}
删除字典的项目:pop()方法或者popitem()方法
语法:pop(key[, default]) popitem()
说明:key:字典的键,以key来删除value,并返回被删除key所对应的值
popitem():无参数,通常会删除第一个项目
例:
dt = {1:'ONE', 2:'two', 3:'three'}
dt.pop(3)
print(dt)
dt.popitem()
print(dt)
输出结果:
{1: 'ONE', 2: 'two'}
{1: 'ONE'}
setdefault()方法:若字典中有此参数key,则返回对应key的value值,
若参数key不在字典中,则该参数key自动成为字典的key,value会以默认值None补上,再以[]运算符指定新值
例;
dt = {1:'ONE', 2:'two', 3:'three'}
print(dt.setdefault(1))
print(dt.setdefault(4))
print(dt)
print(dt.setdefault(5,'five'))
print(dt)
输出结果;
ONE
None
{1: 'ONE', 2: 'two', 3: 'three', 4: None}
five
{1: 'ONE', 2: 'two', 3: 'three', 4: None, 5: 'five'}
字典推导式:
语法:{key表达式 : Value表达式 for key, value in iterable}
{Key表达式 : Value表达式 for key, value in iterable
if 表达式}
例:
#使用字典推导式反转字典的键与值
dt = {1:'ONE', 2:'two', 3:'three'}
print({v:k for k,v in dt.items()})
输出结果:{'ONE': 1, 'two': 2, 'three': 3}
#字典推导式配合zip()函数来创建一个字典
result = {key:value for(key,value) in zip([1,2,3], ['one', 'two', 'three'])}
print(result)
输出结果:{1: 'one', 2: 'two', 3: 'three'}
默认字典和有序字典:dict有两个子类:defaultdict和OrderedDict,都来自于collections模块
defaultdict(默认字典):为字典提供键来取值
OrderedDict(有序字典):可以记住字典插入项目的位置
默认字典:由collections模块的defaultdict类所提供,是dict的子类,可使用dict的所有属性和方法
构造函数defaultdict():可自动配键
语法:defaultdict([default_factory[, ...]])
说明:default_factory:默认工厂函数(工厂函数是指函数被调用后会以特定类型的对象返回)
例;
from collections import defaultdict
df = defaultdict(int)
df['one']
df['two']
df['three'] = 3
print(df)
print(list(df))
print(tuple(df))
print(dict(df))
输出结果:
defaultdict(<class 'int'>, {'one': 0, 'two': 0, 'three': 3})
['one', 'two', 'three']
('one', 'two', 'three')
{'one': 0, 'two': 0, 'three': 3}
#用defaultdict()构造函数来统计字符中出现的次数:
例:
from collections import defaultdict
wd = 'initially'
df = defaultdict(int) #使用defaultdict()构造函数,以int()函数作为它的参数
for key in wd:
df[key] += 1 #使用for循环读取字符串,以每个字符为key,而value的默认值是0,碰到相同字符就累加value,这样就可以统计字符出现的次数
print(list(df.items()))
输出结果:[('i', 3), ('n', 1), ('t', 1), ('a', 1), ('l', 2), ('y', 1)]
有序字典:默认字典无顺序性,有序字典在存储时会记住插入项目的顺序
构造函数OrderedDict():
语法:OrderedDict([items])
说明:会返回dict的子类,并完全支持dict的方法
例:使用OrderedDict()来插入字典的项目:
from collections import OrderedDict
rdt = OrderedDict()
rdt[1] = 'one'
rdt[2] = 'two'
print(rdt)
输出结果:OrderedDict([(1, 'one'), (2, 'two')])
有序字典提供的popitem()方法:用于删除字典的项目
语法:popitem(last = True)
说明:参数last = True表示会删除最后一个项目,last = False会删除第一个项目并返回删除的项目
例:
from collections import OrderedDict
rdt = OrderedDict()
rdt[1] = 'one'
rdt[2] = 'two'
rdt[3] = 'three'
print(rdt)
rdt.popitem(last = True)
print(rdt)
rdt.popitem(last = False)
print(rdt)
输出结果:
OrderedDict([(1, 'one'), (2, 'two'), (3, 'three')])
OrderedDict([(1, 'one'), (2, 'two')])
OrderedDict([(2, 'two')])
move_to_end()方法用来移动字典的项目
语法:move_to_end(key, last = True)
说明:key:字典的键, last = True为默认值,表示会将字典的项目移动到最后一个
例:
先创建无序字典dt,再以OrderDict()方法将此字典转成有序字典
from collections import OrderedDict
dt = {'A':1, 'B':2, 'C':3, 'D':4}
odt = OrderedDict(dt) #转换成有序字典
odt['E'] = 5 #添加一个项目
print(odt)
输出结果:OrderedDict([('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5)])
odt.move_to_end('A')
print(odt)
输出结果:OrderedDict([('B', 2), ('C', 3), ('D', 4), ('E', 5), ('A', 1)])
odt.move_to_end('C', last=False)
print(odt)
输出结果:OrderedDict([('C', 3), ('B', 2), ('D', 4), ('E', 5), ('A', 1)])
内置函数sorted()
语法:sorted(iterable[, key][, reverse])
说明:key:含有参数的函数。表示使用key时要先定义函数,再带入函数。此处可用lambda函数
例:
from collections import OrderedDict
stud = {'Mary':87, 'Eric':49, 'David':81}
#BIF sorted()函数,使用key来排序
name = OrderedDict(sorted(stud.items(), key=lambda fd:fd[0]))
print('按名字进行升序排列')
for key in name:
print('%5s'%key, name[key])
输出结果: 按名字进行升序排列
David 81
Eric 49
Mary 87
集合
45.集合:
集合的特色:
无序的群集数据,以{}创建集合并存放集合元素
成员测试。使用成员运算符in/not in 来判断某元素是否在集合内
内置函数len()可获取set对象的长度
可以对比序列对象,删除重复的项目
支持数学运算
集合本身无序,不会记录元素的位置,也不支持索引、切片运算
set类型的两个类:set 和frozenset的差异性
set frozenset
可变 可变(mutable) 不可变(immutable)
哈希值 无 可哈希
当作字典的key 不能 能
另一个set元素 不可以 可以
add()方法添加元素 可以 不可以(大小固定)
例:
>>> data = ['Mary', 'Tomas']
>>> st = set(data) #可变set
>>> st.add('Judy')
>>> st
{'Tomas', 'Mary', 'Judy'}
>>> fst = frozenset(data)
>>> fst.add('Peter')
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
fst.add('Peter')
AttributeError: 'frozenset' object has no attribute 'add'
什么是哈希:使用哈希函数将检索的项目和哈希值(生成检索的索引)建立关联,便于在哈希表中检索
哈希函数/哈希算法:为任何形式的数据生成小的“数字指纹”,作用:①固定数据的格式,将数据或信息压缩变小②将数据打散并混合,重新创建“哈希值”的指纹
哈希值是由随机字母和数字生成的字符串
字计算机数据安全上,通过“哈希”可以辨别文件与数据是否被篡改
"可哈希的"对象的所要条件:
特殊方法__hash__()可以返回哈希值
所产生的哈希值在生命周期内是维持不变的
特殊方法__eq__()可以进行相等与否的比较
内置函数issubclass()来判断类型是否是“可哈希的对象”,如果返回值是True,则能确定是它的某个子类(float,frozenset,int,str,tuple均可哈希,list是不可变对象不可哈希)
语法:issubclass(class, classinfo)
说明:class:要进行确认的子类 classinfo:类名称
例:
from collections.abc import Hashable #Hashable类由collections.abc模块提供
print(issubclass(set, Hashable))
print(issubclass(frozenset, Hashable))
输出结果:False
True
集合对象的创建:
使用{}来存放集合的元素,集合的元素可以是数值、字符串、元组
例:
>>> x = {11,12,13}
>>> y = {'one', (2, 5)}
>>> z = {'two', [11, 22]} #列表是可变对象,不可存放在集合中
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
z = {'two', [11, 22]}
TypeError: unhashable type: 'list'
使用内置函数set(),以可迭代对象作为集合的元素
语法:set([iterable])
说明:itreable:可迭代对象,只能传入一个参数;列表或集合对象无法直接成为集合的元素,但可以通过set()函数成为集合的元素
例:
>>> st1 = set(['one','two','three']) #列表转换为集合元素
>>> st1
{'two', 'three', 'one'}
>>> st2 = set((25, 'size'), 'world') #set()函数放入两个参数,一个是元组一个是字符串,参数太多会引发错误
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
st2 = set((25, 'size'), 'world')
TypeError: set expected at most 1 arguments, got 2
>>> #配合ange()函数创建迭代器
>>> st1 = set(range(11, 16))
>>> st1
{11, 12, 13, 14, 15}
>>> wd = 'hello'
>>> print(set(wd)) #集合会将重复的数据删除,因此使用set()函数将字符串转换为元素时重复的字符只取一个
{'o', 'e', 'h', 'l'}
集合的相关操作:
s.add(x):将数据项x加入集合s中,不可添加列表
s.clear():清除集合s中的所有元素
s.copy():以浅复制返回集合s的副本
s.discard(x):从集合s中删除数据项x,无此项不报错
s.pop():从集合s中随机删除数据项并返回其值
s.remove(x):从集合s删除数据项x,如果无此项时会引发错误
len(s):获取集合的长度
集合的数学计算:
|:并集,生成新的集合(去除重复项目)
&:交集:两个集合之间共有的项目
-:差集,可以看做两个集合相减
^(XOR):相对差集,两个集合相间所得再并集
s.union(other,...):等同于s|other,新建集合,去重重复元素
s.intersection(other,...):等同于s&other,新建集合
s.difference(other, ...):等同s-other,以s为主来新建集合
s.symmetric_difference(other):等同s^other,新建集合,具有s个t的元素,但排除同时存在的元素
s.update(other, ...):等同s |= other,将t的元素加入s集合,去除重复项目,s集合原地修改
s.intersection_upfate(other,...):等同s&=other,s集合原地修改
s.difference_update(other,...):等同s -= other,s集合原地修改
s.symmetric_difference_update(other,...):等同s ^= other,s集合原地修改
并集运算:将两个集合的元素放在一起构成一个新集合,重复元素被剔除。并集运算时使用|或union()方法:
例;
>>> st1 = {11,22,33}
>>> st2 = {11, 23, 34}
>>> st1 | st2
{33, 34, 22, 23, 11}
>>> st1.union(st2)
{33, 34, 22, 23, 11}
>>> st1.union([11,56,78])
{33, 11, 78, 22, 56}
>>> st1.union('one',('two',24))
{33, 'two', 'o', 11, 'e', 'n', 22, 24}
交集运算:找出两个集合中共有的元素来创建一个新集合,使用&运算符或者intersection()方法
例:
>>> st1 = {11,22,33}
>>> st2 = {11, 23, 34}
>>> st1 & st2
{11}
>>> st1.intersection(st2)
{11}
>>> st1.intersection((11,22,33))
{33, 11, 22}
差集运算:将两个集合相减,如果是A - B,其结果以A为主新建一个集合,如果是B-A,其结果会以B为主新建一个集合,运算符用 - 或用difference()方法
例:
>>> st1 = {11,22,33}
>>> st2 = {11, 23, 34}
>>> st1 - st2
{33, 22}
>>> st2 - st1
{34, 23}
>>> st1.difference(st2)
{33, 22}
>>> st2.difference(st1)
{34, 23}
>>> st1.difference([11,45,78])
{33, 22}
>>> st2.difference((11,34,56))
{23}
对称差集运算:对称差集(XOR异或),是指将两个集合互减之后再做并集运算。使用运算符 ^ 或symmetric_difference()方法
例:
>>> st1 = {11,22,33}
>>> st2 = {11, 23, 34}
>>> st1 ^ st2
{33, 34, 22, 23}
>>> (st1 - st2) | (st2 - st1)
{33, 34, 22, 23}
>>> st1.symmetric_difference(st2)
{33, 34, 22, 23}
>>> st1.symmetric_difference([78, 24])
{33, 11, 78, 22, 24}
增强运算:使用update()方法有增强运算的作用,相关方法如果含有update字符串则表示该方法有增强作用。
update()方法本身等同增强并集的运算。update()方法可视为增加集合元素的方法,由于集合本身隶属于可变对象,
因此使用add()方法来加入另一个集合会报错。使用update()方法不会产生新集合,而是原地修改调用此方法的集合
例:
>>> st1 = {11,22,33}
>>> st2 = {11, 23, 34}
>>> st1,st2
({33, 11, 22}, {34, 11, 23})
>>> st1.update(st2) #st1 |= st2
>>> st1,st2
({33, 34, 22, 23, 11}, {34, 11, 23})
交集计算的增强版:调用intersection_update()方法,即执行 st1 &= st2
例:
注:获取st1 和st2两个集合的交集,结果会改写st1集合的项目
>>> st1 = {11,22,33}
>>> st2 = {11, 23, 34}
>>> st1,st2
({33, 11, 22}, {34, 11, 23})
>>> st1 &= st2
>>> st1
{11}
>>> st1.intersection_update(st2)
>>> st1
{11}
注:如果两个集合没有交集,就会返回set()函数,表示st1是一个空集合
例:
>>> st1 = {11,12,13}
>>> st2 = {22,24,26}
>>> st1.intersection_update(st2)
>>> st1
set()
调用difference_update()方法等同于执行差集计算的增强作用,就是计算st1 -= st2计算
注:调用difference_update()进行增强差集运算,以st1 为主和以st2为主所得结果会不同
例:
>>> st1 = {11,12,13,14}
>>> st2 = {12,13,24,28}
>>> st1.difference_update(st2)
>>> st1
{11, 14}
>>> st1 = {11,12,13,14}
>>> st2 = {12,13,24,28}
>>> st1 -= st2
>>> st1
{11, 14}
>>> st1 = {11,12,13,14}
>>> st2 = {12,13,24,28}
>>> st2.difference_update(st1)
>>> st2
{24, 28}
>>> st1 = {11,12,13,14}
>>> st2 = {12,13,24,28}
>>> st2 -= st1
>>> st2
{24, 28}
调用symmetric_difference_update()方法等同执行st1 ^= st2
例:
>>> st1 = {11,12,13,14}
>>> st2 = {12,13,24,28}
>>> st1 ^= st2
>>> st1
{11, 14, 24, 28}
>>> st1.symmetric_difference_update(st2)
>>> st1
{11, 12, 14, 13}
父子集合相关方法:
s > other:测试集合s是否是other的父集合(左集合是否是右集合的父集合)
s<other:测试s集合是否是other的子集合
s.issuperset(other):等同s>other,返回值为True表示other为子集合
s.isdisjoint(other):s与other无共同元素时,返回True
s.issubset(other):等同s<other,True表示other为父集合
注:无论使用运算符>=还是issuperset()都会逐一对比other集合的每个元素是否也在s集合里,若比较属实,s就为other的父集合
例:
>>> st1 = {11,12,13,14}
>>> st2 = {12,13}
>>> st1.issuperset(st1)
True
>>> st1.issuperset(st2)
True
>>> st1 >= st2
True
>>> st1.issubset(st2)
False
>>> st1 <= st2
False
isdisjoint()方法:
例:
>>> st1 = {11,12}
>>> st2 = {13,14}
>>> st1.isdisjoint(st2)
True
>>> st1 = {11,12,13}
>>> st2 ={14,15}
>>> st2.isdisjoint(st1)
True
集合推导式:使用集合推导式要考虑集合本身是可变的,且无序输出,要想正确获取处理后的结果,可配合字典、元组、列表来产生字典推导式
语法:{表达式 for item in iterable}
{表达式 for item in iterable if 条件表达式}
例:使用集合推导式获取列表每个元素的长度
>>> fruit = ['banana', 'apple', 'morello', 'strawberry', 'pineapple']
>>> print({len(item) for item in fruit})
{5, 6, 7, 9, 10}
函数
46.函数:
使用函数优点:
实现信息模块化的目标
函数或方法可以重复利用,便于日后的调试和维护
从面向对象的角度看,函数提供了操作接口的方法,有数据隐藏的作用
python函数分类:系统内置函数(BIF)、python提供的标准函数库、使用def关键字自定义的函数
内置函数:
与数值有关的内置函数:
int():整数转换成整数类型
bin():把整数转换成二进制,以字符串返回
hex():把整数转换成十六进制,以字符串返回
oct():把整数转换成八进制,以字符串返回
float():转换为浮点数类型
complex();转换为复数类型
abs():取绝对值,参数可以是整数、浮点数、复数
divmod():a//b求商,a%b取余,a、b为数值
pow():x**y,(x**y)%z
round():将数值四舍五入
用来进行逻辑判断的内置函数
bool():布尔值
all():返回布尔值,判断元素是否是iterable
any():返回布尔值,判断元素是否是iterable
与字符串有关的内置函数
str():字符串或转为字符串类型
chr():将ASCII数值转为单个数值
ord():将单个字符转为ASCII数值
ascii():以参数返回可打印的字符串
repr():返回可代表对象的字符串
format():根据规则将字符串格式化
与迭代器有关的内置函数:
iter():返回迭代器
next():返回迭代器的下一个
zip():聚合两个可迭代器
range():返回range对象
enumerate();列举迭代器时加入索引
filter():按其函数的定义来过滤迭代器
与序列类型有关的内置函数:
list():列表或转换为列表对象
tuple():元组或转换为元组对象
len():返回对象的长度
max():找出最大的
min():找出最小的
slice():切片
reversed():反转元素,以迭代器返回
sum():计算总和
sorted():排序(元组)
与字典、集合有关的内置函数
dict():字典或转换为字典对象
set():集合或转换为集合对象
frozenset():不可变的集合
与对象有关的内置函数
id():返回对象的标识符
type():返回对象的类型
hash():返回对象的哈希值
object():创建基本的对象
super():返回代理对象,委派方法调用父类
issubclass():判断类是否为指定类的子类
classmethod():类方法
staticmethod():静态方法
isinstance():判断对象是否是指定类的实例
getattr():获取对象的属性
setattr():设置对象的属性
hashattr():判断对象是否有属性
delattr():删除对象的属性
property():属性
memoryview():返回“内存查看”对象
其他内置函数
bytearray():可变的字节数组
bytes():字节
print():输出字符串到屏幕上
input():获取输入的数据
open():打开文件
__import__():用于底层的import语句
compile():编译源代码
eval():动态执行python表达式
exec():动态执行python语句
globals():返回全局命名空间的字典
locals():返回局部命名空间的字典
dir(object):列示当前作用域内的名称
help():启动内置文件系统
函数基础:
定义函数:
语法: def 函数名称(参数列表):
函数主体_suite
[return值]
说明:def是定义函数的关键字,为函数程序区块的开头,尾端要有 :
函数名称:遵守标识符名称的命名规范
参数列表:或称为形式参数列表,用来接收数值,其名称也适用于标识符名称的命名规则,可以有多个参数,也可省略参数
函数主体必须缩排,可以是单行或多行语句
return:用来返回运算后的值,如果无数值运算,return语句就可以省略
注意:参数和参数值的不同:
参数(parameter):定义函数时用来接收数据
参数值(argument):调用函数时,接收数据之后,还得进一步执行传递操作
返回值:
返回单个的值或对象
多个值或对象可以存储在元组对象中
未使用return语句时,默认返回None
参数的基本机制:使用函数时可进行不同参数的传递和接受
实际参数:在程序中调用函数时,将接受的数据或对象传递给自定义函数,默认为位置参数
形式参数:定义函数时,用来接收实际参数所传递的数据,进入函数主体执行语句或运算,默认以位置参数为主
实参、实参的使用方法:
默认参数值:让自定义函数的形式参数采用默认值的方式,当实际参数未传递时,以 默认参数 = 值 进行接收
关键字参数:调用函数时,实际参数直接以形式参数为名称,配合设置值传递数据
使用 * 和 **表达式/运算符。配合形参, * 表达式以元组组成, ** 表达式以字典相辅,可以接受实参,通过实参,*可以拆分迭代对象,**能拆分映射对象,让形参接收
参数如何传递:
其他语言参数传递方式:
传值:若为数值数据,则先把数值赋值一份再传递,原有参数内容不会受到影响
传址:传递的是参数的内存地址,会改变原有变量内容
python传参方式:
不可变对象(数值、字符串等):使用对象引用时会先复制一份再传递,接近传值方式
可变对象(列表等):使用对象引用时会直接传递内存地址,即传址
默认参数值:自定义函数时,将形参给予默认值,当调用函数时某个参数没有传递数据时,自定义函数可以使用其默认值
语法: def 函数名称(参数1, 默认参数2 = value2, ...):
函数主体_suite
说明:第一个形参必须是位置参数,第二个形参才是默认参数,并且要同时设置其值。
使用默认参数值能让实参传递时更有弹性,但必须遵守以下规则:
若有位置参数加入,必须放在默认参数值之前
默认参数值对于不可变和不可变对象会有不同的执行结果
默认参数值若为不可变对象,则只执行一次运算,当形式参数为默认参数值时,无论是字符串还是表达式(不可变对象),都会被实际参数所传递的对象取代
但形参赋值的是可变对象(如列表对象)会积累内容,可能产生意想不到的结果
例:
>>> def number(x, y = []):
y.append(x)
print(y, end = '')
>>> number(2)
[2]
>>> number(3)
[2, 3]
>>> number(4)
[2, 3, 4]
说明:调用number()函数时实际参数传递的值都会被保留,以列表的元素列示函数的执行结果。因此只有第一次执行时y才是空列表
#每次执行时都由空列表开始
>>> def number(x, y=[]):
if y is not None:
y = []
y.append(x)
print(y,end = '')
>>> number(3)
[3]
>>> number(2)
[2]
注意:python的None与其他语言不太一样:
使用布尔值判断会返回False
用来保留对象的位置,可以用is运算符进行判断
关键字参数:直接定义函数的形参为名称,不需要按其位置来给参数赋值
语法:functionName{kwarg = value1, ...}
说明:调用函数时,直接以函数所定义的参数为参数名,并设置其值进行参数传递的操作;关键字可随意指定,但要指出形参的名称
例:
>>> def calc(x,y):
return x**2 + y//2
>>> calc(y = 6, x = 12)
147
形参的*表达式:*一般用于乘法计算,在自定义函数中形参用于表达式,用来收集位置参数,但参数不足时会报错
语法: def 函数名称(参数1, 参数2,..., 参数N, *tp):
函数主体_suite
说明:*tp:*表达式要配合元组对象来收集额外的实际参数
例:解开一个可迭代对象来取出若干元素时,可以使用*表达式
#使用元组的Unpacking运算,所以name的指向David,sex的值指向Male。*score就是型号表达式,会接受pern中其他元素
pern = ('David', 'Male', 1, 12, 13)
name,sex, *score = pern
print(name)
print(score)
例:搭配元组来收集多余的实参
#自定义函数calcu()只有一个形参value,且为*表达式,调用此函数所传递的参数都会放入value中,以元组输出元素
def calcu(*value):
result = 1
for item in value:
result *= item
return result
print('1个参数:', calcu(7))
print('3个参数:', calcu(2, 3, 5))
输出结果:1个参数: 7
3个参数: 30
例3:
def student(name, *score, subject = 4):
if subject >= 1:
print('名字:', name)
print('共有', subject, '科,分数:', *score)
total = sum(score)
print('总分:', total, ',平均:', '%.4f'%(total/subject))
student('Tomas', 78, 65, 93, 84)
student('Mary', 67, 78, 67, subject=3)
student('Fitz', 78, subject=1)
输出结果:
名字: Tomas
共有 4 科,分数: 78 65 93 84
总分: 320 ,平均: 80.0000
名字: Mary
共有 3 科,分数: 67 78 67
总分: 212 ,平均: 70.6667
名字: Fitz
共有 1 科,分数: 78
总分: 78 ,平均: 78.0000
**表达式与字典配合:
语法: def 函数名称(**dict):
函数主体_suite
说明:单一形参,使用**表达式,配合空的字典对象接收关键字参数
调用函数时,关键字参数会以 实际参数 = 值 来传递
例:
def score(**value):
print('成绩', value)
score(eng = 67, comp = 95, math = 99)
输出结果:成绩 {'eng': 67, 'comp': 95, 'math': 99}
定义函数时,双星表达式**之前也可以加入位置参数
语法: def 函数名称(参数1, 参数2, ..., 参数N, **dict):
函数主体_suite
说明:位置函数必须在字典对象之前,否则会报错
**dict:双星表达式,接受的关键字参数都会放入字典对象中
例:#调用stud()函数要带入更多的参数,必须以关键字参数key = value来产生
def stud(name, **dt):
print('Name:', name)
print('Score', dt)
#调用函数,1个位置参数
stud('Mary')
#调用函数,一个位置参数3个关键字参数
stud('Tomas',eng = 60, math = 99, chinese = 100)
输出结果:
Name: Mary
Score {}
Name: Tomas
Score {'eng': 60, 'math': 99, 'chinese': 100}
*表达式和**表达式同时使用:定义函数时,*表达式配合元组对象能收集多余的位置参数,**表达式在字典的配合下可收集多余的关键字参数
语法: def 函数名称(*tuple, **dict):
函数主体_suite
def 函数名称(参数1, 参数2, ..., 参数N, tuple, **dict):
函数主体_suite
说明:形参有两个,第一个是*表达式,用于手机位置参数,第二个是**表达式,放入多余的关键字参数
自定义函数形参若是位置参数,则必须放在*和**表达式之前
例:
def fun(*name, **value):
print('颜色', name)
print(value)
#调用函数时,传入3个位置参数,它会被形参的name放入元组,而3个关键字参数会由形参value接收,成为字典项目
fun('Green', 'Blue', 'Red', g = (0, 255, 0), b = (0, 0, 255), r = (255, 0, 0))
输出结果:
颜色 ('Green', 'Blue', 'Red')
{'g': (0, 255, 0), 'b': (0, 0, 255), 'r': (255, 0, 0)}
*运算符拆分可迭代对象:调用函数时,实参传递数据同样能用*运算符来拆分可迭代对象,而形参会以位置参数来接收这些可迭代对象的元素
例:#自定义函数number()形参有5个,都是位置参数,调用函数时,数值11和12是位置函数,range()函数提供可迭代对象13,14,15,
#使用*表达式解开后共有5个位置参数
def number(n1, n2, n3, n4, n5):
print('Number', n1, n2, n3, n4, n5)
#调用函数,使用*运算符来拆分可迭代对象
print('后两个是可迭代对象')
number(11, 12, *range(13, 16))
输出结果:
后两个是可迭代对象
Number 11 12 13 14 15
例2:
def score(name, n1, n2, n3):
print(name)
print('分数:', n1, n2, n3)
total = n1 + n2 +n3
average = total/3
print('总分:', total, '平均:{0:.4f}'.format(average))
number = [78, 94, 35]
#调用函数 number列表对象,可迭代
score("Tomas", *number)
输出结果:
Tomas
分数: 78 94 35
总分: 207 平均:69.0000
**运算符拆分字典对象:
调用函数时,映射拆分运算符**可拆分映射类型的对象,通常以字典为主。拆分字典项目时,key要作为形参的名称,用它来接收字典对象的value
例:
data = {'x':78, 'y':56, 'z':92} #定义dict
#自定义函数,形参的x,y,z来自dict的key
def student(n1, n2, n3, x, y, z):
print('%6s'%n1, '%3d'%x)
print('%6s'%n2, '%3d'%y)
print('%6s'%n3, '%3d'%z)
#调用函数,第四个实参为字典对象,使用**运算符
#data为字典对象,{}里的项目由key:value组成,其中的key:x,y,z由**运算符拆分后转化为定义函数形参,
#成为3个位置参数,再加上其它3个位置参数,共6个形参
student('Eric', 'Tom', 'Ivy', **data)
输出结果:
Eric 78
Tom 56
Ivy 92
注意:调用函数student()所传入的位置参数只有2个,分别是'One'和'Two',参数不足会发生错误;student('One','Two',**data)
定义函数student()时未把字典的key放入形参中或设错名称,调用函数时报错;def student(n1,n2,n3,x,y,a)
调用函数时,必须以字典对象名称data为关键参数,如果不是会报NameError错误
更多函数的讨论:
作用域:
全局作用域:适用于整个文件(*.py)
局部作用域:适用于所有声明的函数或流程控制的程序区块,离开此范围就会结束其生命周期
内置作用域:由内置函数通过builtins模块所拥有,可以在在不同文件内使用
根据作用域可创建4种函数:全局函数、局部函数、lambda函数和方法
全局函数:表示整个文件都适用,一般定义的函数都是
局部函数:函数中再定义函数
lambda()函数:以运算为主的匿名函数,可以用来取代小函数
方法:泛指类或对象所使用的方法。如创建列表对象后用append()方法来添加元素
作用域:内置作用域是最大的命名空间,而后是较小的全局作用域,最小的是局部作用域
例:
#定义函数,有5个形参
def total(name, n1, n2, n3, n4):
result = 0 #result是局部变量,作用域只能在函数中
result = sum(price) #sum内置作用域
print(name, '$', result
#创建可迭代对象序列对象
price = [78, 92, 65, 55] #price全局变量,整个文件都是它作用域
total('dinner', *price)
输出结果:dinner $ 290
注意:当变量为全局变量时才能存储累加的结果
全局变量:变量在函数程序区块外声明,一般就是全局变量,使用方法:
例:
fruit = 'Orange'
def favorite():
print('最喜欢的水果', fruit)
favorite()
输出结果:最喜欢的水果 Orange
局部变量和全局变量同名问题:
例:#局部变量在赋值前已经给定值了,会造成全局变量和局部变量造成混乱
>>> fruit = 'Orange'
>>> def summer():
print('最爱水果:', fruit)
fruit = '大西瓜' #改变全局变量的值
print('夏日水果是:', fruit)
>>> summer()
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
summer()
File "<pyshell#29>", line 2, in summer
print('最爱水果:', fruit)
UnboundLocalError: local variable 'fruit' referenced before assignment
更改后解决问题:
调用summer()函数时,系统会先从作用域小的局部变量找起,再从程序区块外围找出是否有全局变量
位于summer()函数的局部变量fruit会优先输出 夏日水果 大西瓜 ,所以不会出错
>>> fruit = 'Orange' #全局变量
>>> def summer():
fruit = '大西瓜' #局部变量
print('夏日水果', fruit)
>>> summer()
夏日水果 大西瓜
使用关键字global:当全局变量和局部变量同名且又要同时要在自定义函数中使用时,为了不让彼此之间起冲突,需要在函数内将全局变量冠上global关键字(不是好方法,应避免使用同名变量)
Python处理局部、全局和内置作用域变量的方法:
变量可用于不同作用域内,若是同名,则局部变量的优先权高于全局变量,而全局范围高于内置作用域
变量第一次创建名称的地方代表它的作用域。执行时,作用域从小到大,从局部变量到全局变量,最后到内置作用域
局部函数与闭包:
局部函数:在函数中定义其他函数,后者被称为内部函数、局部函数或嵌套函数
例:局部函数:
def exter(x, y):
def internal(a, b):
return divmod(a, b)
return internal(x, y)
print(exter(25, 7))
输出结果:(3, 4)
闭包:指一种由其他函数主动产生的函数(如outer()函数),能直接引用包裹该函数(inner()函数)所定义的局部变量(y),
而局部变量(y)不会因为离开该函数(outer()函数)作用域而结束其生命周期
例:闭包:
def outer(x):
def inner(y):
return x ** y
return inner
print(outer(5)(6))
输出结果:15625
例2:
#定义函数total = 0
def allNums(total):
def oneFun(item, step):
nonlocal total
print('数值', end = '')
for item in range(1, item + 1, step):
print('%3d'%item, end='')
total += item
print()
return total #返回累加结果
return oneFun #返回函数对象
#调用函数
star = allNums(0) #total = 0
#star 配合range(1, 20, 3)函数进行累加
print('合计:', star(20, 3))
输出结果: 数值 1 4 7 10 13 16 19
合计: 70
lambda表达式:又称lambda表达式,无函数名称
语法:lambda 参数列表,... : 表达式
说明:参数列表使用逗号隔开,表达式之前的冒号:不能省略、 lambda表达式只有一行语句、 lambda表达式不能使用return语句
例:
f = lambda x, y : x**y
print(f(2,3))
输出结果:8
注:使用lambda表达式时要指定一个变量来存储运算的结果,再调用lambda表达式,否则表示没有对象引用最后被系统作为垃圾回收
filter(function, iterable)函数:可以将迭代器的元素根据参数function的设置进行过滤,它会返回True的元素,
并以序列类型(List、String、Tuple)来组成,同样的,会剔除返回False的元素
语法:filter(function, iterable)
说明:function:表示将定义一个函数或使用lambda表达式、 iterable:表示迭代器的可迭代元素
例:
#定义简单函数
def getNum(x):
return x > 2
#可迭代对象,用range()函数来生成
lt = range(10)
#所得结果用列表转换
print(list(filter(getNum, lt)))
输出结果:[3, 4, 5, 6, 7, 8, 9]
例2:filter()函数的function参数可用lambda表达式代替:
lst = range(1, 16)
print(list(filter(lambda x : x % 3 == 0, lst)))
输出结果:[3, 6, 9, 12, 15]
递归:函数的自我调用
例1:正整数阶乘
import math
print(math.factorial(5))
输出结果:120
例2:函数观点定义阶乘
def fact(x):
upshot = 1 #用于存储阶乘计算结果
for item in range(1, x+1):
upshot *= item
return upshot
print(fact(5))
输出结果:120
例3:递归进行阶乘
def factR(x):
if x <= 1: #0! = 1! = 1
return 1
else:
return (x * factR(x -1))
print(factR(5))
输出结果:120
例4:利用迭代输出斐波那契数列
def fiboA(num):
result = [] #用于存储斐波那契数列
a, b = 0, 1
while b < num:
result.append(b)
a, b = b, a+b
return result
print('斐波那契数列:', fiboA(10))
输出结果:斐波那契数列前10项是: [1, 1, 2, 3, 5, 8]
例5:利用递归输出斐波那契数列
#斐波那契数列:当n=0或n=1时,可用fib(n)表示,当 n = (n-1项) + (n-2项)可用fib(n-1) + fib(n-2)
def fibo(x):
if x <= 1:
return x
else:
return fibo(x -1) + fibo(x - 2)
#定义空列表用于存放斐波那契数列
lst = []
for item in range(10):
lst.append(fibo(item))
print('递归版斐波那契数列:', lst)
输出结果:递归版斐波那契数列: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
面向对象
48.面向对象:将真实世界的事物模块化,主要目的是提供软件的可重用性和可读性
类与对象:
python类的特性:
Python所有的类与其包含的成员都是public,使用时不用声明该类的类型
采用多重继承,派生类可以和基类的方法重名,也能覆盖所有基类的任何方法
定义类:类由类成员组成,使用类之前要进行声明
语法:calss ClassName():
#定义初始化内容
#定义methods
说明:class:使用关键字创建类,配合 : 来产生suite
ClassName:创建类使用的名称,同样必须遵守标识符的命名规范
method:定义method时,与定义函数相同,使用关键字def
例:创建一类空类
class student:
pass
#创建一个student类,使用pass语句表示什么都不做,可省略
Python类的特性的不同点:
每个类都可以实例化多个对象。经由类创建的新对象都能获得自己的命名空间,能独立存放数据
经由继承扩充类的属性。自定义类后可建立命名空间的分层架构,在类外部重新定义其属性来扩充属性,定义多项行为时更优于其他工具
运算符重载。经由特定的协议来定义类的对象,响应内置类型的运算,如切片、索引等
定义方法:通常可在定义类的过程中加入属性和方法,在用对象来存取其属性和方法
方法的特点:
只能定义于类的内部
只有实例化(对象)才会被调用
注意:一般来说,绑定会牵引方法的调用,即,当实例去调用方法时才有绑定的操作。根据Python的使用惯例,定义方法的第一个参数必须是自己,
习惯上使用self表示,代表类创建后实例化的对象。self类似于this,指向对象本身
补充:方法中的第一个参数self:
定义类时所有的方法都必须声明它,当对象调用方法时,Python解释器会一同传递它。使用于方法的self参数会绑定所指向的实例
类实例化:创建对象,有了对象之后可进一步存取类中所定义的属性和方法
语法:对象 = ClassName(参数列表)
对象.属性
对象.方法()
说明:对象名称同样要遵循标识符命名规范,参数列表可根据对象初始化进行选择
例1:
class Motor:
#定义方法一:获取名称和颜色
def buildCar(self, name, color):
self.name = name #通过self使其从局部变量变成了对象变量,即属性
self.color = color
#定义方法二,输出名称和颜色
def showMessage(self):
print('款式:{0:6s},颜色:{1:4s}'.format(self.name, self.color))
#创建对象
car1 = Motor()
car1.buildCar('Vios', '极光蓝')
car1.showMessage()
car2 = Motor()
car2.buildCar('Altiss', '炫魅红')
car2.showMessage()
输出结果:
款式:Vios , 颜色:极光蓝
款式:Altiss, 颜色:炫魅红
例2:
class Student:
def message(self, name):
self.data = name #借助self将传入的参数name设为对象属性
def showMessage(self):
print(self.data)
s1 = Student()
s1.message('James McAvoy')
s1.showMessage()
s2 = Student()
s2.message(78.12345)
s2.showMessage()
输出结果:
James McAvoy
78.12345
对象属性:除使用__init__()配合self参数来设置属性之外,还能在创建对象之后动态自定义属性
例:
class Student:
def message(self, name):
self.data = name
def showMessage(self):
print(self.data)
Tomas = Student()
Tomas.subject = []
Tomas.subject.append('math')
print(Tomas.subject)
输出结果:['math']
补充:
定义类的方法第一个参数要使用self语句,而self指向实例化的对象本身
实例化对象就如同调用函数一般,可创建多个对象,创建对象之后还能动态增加对象的属性
因此,对象就像是一个内含记录的数据,而类则是处理这些数据的程序
先构造再初始化对象:
步骤:1、调用特殊方法__new__()来创建对象 2、再调用特殊方法__init__()来初始化对象
__new__()方法创建对象
语法:object.__new__(cls[, ...])
说明:object:类实例化所创建的对象
cls:创建cls类的实例,通常会传入用户自定义的类
其余参数可用于创建对象
注意:__new__()方法可以决定对象的创建,如果第一个参数返回的对象是类实例,就会调用__init__()方法继续执行(如果__init__()已经定义),
它的第一个参数会指向对象所返回的对象。如果第一个参数未返回其类实例(返回别的实例或None),__init__()方法即使定义也不会执行
__init__()方法初始化对象:
__new__()方法是一个静态方法,几乎包含了创建对象的所有要求,Python解释器会自动调用它,当对象初始化时,python会重载__init__()方法
语法:object.__init__(self[, ...])
说明:object为类实例化所创建的对象
使用__init__()方法的第一个参数必须是self语句,后续的参数可根据实际要求来覆盖此方法
补充:何为重载?
定义函数时,名称相同饭但参数列表不同,解释执行时,由python解释器根据参数的多寡决定所要调用的函数
例:
class newClass:
#__new__()创建对象
def __new__(Kind, name):
if name != '':
print('对象已创建')
return object.__new__(Kind)
else:
print('对象未创建')
return None
#__init__()初始化对象
def __init__(self, name):
print('对象初始化...')
print(name)
x = newClass('')
print()
y = newClass('second')
输出结果:
对象未创建
对象已创建
对象初始化...
second
设置、检查对象的属性:
getattr():存取对象的属性
语法:getattr(object, name[, default])
说明:object:对象, name:属性名称,必须是字符串类型, default:若无此信息,则可使用此参数输出相关信息
例:
getattr(p1, 'name') #获取name属性值
getattr(p1, 'name', None) #获取name属性值,若无name属性值,则以None表示
hasattr(obj, name):检查某个属性是否存在
delattr():删除一个属性
setattr():设只属性,如果该属性不存在,则新建一个属性
语法:setattr(object, name, value)
说明:object对象, name:属性名称, value:属性值
例:
class Student():
pass
Json = Student() #创建对象
setattr(Json, 'age', 25)
print(getattr(Json, 'age'))
delattr(Json, 'age')
print(hasattr(Json, 'age'))
输出结果:
25
False
处理对象的特殊方法:
__del__():也叫析构函数,用来清除对象
__str__():定义字符串格式,调用BIF的str()、format()、print()时都可以输出
__repr__():调用repr时,重建符合此格式的字符串对象,并将重建好的对象返回
__format__():调用format()函数时,字符串对象以格式化字符串形式返回
__hash__():调用hash()函数计算哈希值
__getattr__():在正常地方无法找到属性时会调用此方法
__setattr__():调用此方法来设置属性
__delattr__():调用此方法来删除某个属性
__getattribute__():任何情况下都可以调用此方法寻找属性
__dir__():返回含有对象属性的列表对象
__class__():属性,用来指向实例的类型
处理字符串的特殊方法:
object.__repr__(self)
object.__str__(self)
object.__format__(self, format_spec)
说明:object:对象,format_spec:格式化字符串
例:
class Birth():
def __init__(self, name, y, m, d):
self.title = name
self.year = y #年
self.month = m #月
self.date = d #日
def __str__(self):
print('您好,亲爱的', self.title)
return 'Birth - ' + str(self.year) + '年' + str(self.month) + '月' + str(self.date) + '日'
def __repr__(self):
return '{}年 {}月 {}日'.format(self.year, self.month, self.date)
p1 = Birth('Grace', 1987, 12, 15)
print(p1)
print(p1.title, 'birth day:', repr(p1))
输出结果:
您好,亲爱的 Grace
Birth - 1987年12月15日
Grace birth day: 1987年 12月 15日
回收对象:python提供了垃圾自动回收机制,即某个对象没有被引用时(内置类型和实例化对象),就会被定期清除,释放内存空间
python提供了__del__()方法来回收对象。通过此方法让对象具有回收资格,也就是引用变量计数为0的时候。
通常__del__()方法在对象被回收前才会执行(因为回收对象的时间不一定,建议不要用于要求实时性的情况)
例:
class Testing():
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
MyName = self.__class__.__name__
print('已清除', MyName)
t1 = Testing(15, 20)
t2 = t1
print('t1 = ', id(t1), ', t2 = ', id(t2))
del t1
del t2
输出结果:
t1 = 53082288 , t2 = 53082288
已清除 Testing
模块与函数库
47.模块与函数库
导入模块:
命令行的参数列表:python的模块sys的属性argv获取命令行参数
语法:sys.argv #未加入索引,接收的参数列表会放入列表(List)中
sys.argv[index] #可加入索引值,从0开始,但不会放入列表中
import/as语句:放在程序的开始(*.py文件的开始)
语法:import 模块名称1,模块名称2,...,模块名称N
import 模块名称 as 别名
说明:使用import语句时可以导入多个模块,不同模块用逗号隔开,当模块较长时,允许使用as语句给予别名
例:
#导入python标准模块的数学和随机数模块
import math,random
#名字较长给予简称
import random as rd
from/import 语句:加载模块时,相关的属性和方法也会加载,为了节省资源,可使用“模块名.属性”的方法或只导入模块的某部分,可用from/import语句
语法:from 模块名称 import 对象名
from 模块名称 import 对象名1,对象名2,...,对象名N
#使用*字符表示导入一切非私有软件包。其加载的对象可能与当前编写的程序代码产生冲突,降低了安全性,不建议使用
from 模块名称 import *
from语句配合模块名称,再以import语句指定其属性和方法,若要指定多个对象,要用逗号隔开
#一般使用“类.方法”
import math #导入math数学模块
math.fmod(15, 4) #求余数,返回3.0,调用fmod方法时,因为fmod时math类提供的方法,必须用“.”方式来使用
from marh import factorial,ceil
factorial(5) #返回计算阶乘的结果120(1*2*3*4*5)
ceil(15, 4) #无条件进位之后取整
命名空间与dir()函数:可以把命名空间(Namespace)视为容器,在使用模块时就已建立,会随着对象的产生而有不同命名空间存在。
一般来说,内置函数dir()有无参数时都会有不同的回应
例:dir()函数无参时会找出当前作用域以定义的名称
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
例:dir()函数有参时会列举相关的信息,如math模块的属性和方法
>>> import math
>>> dir(math)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh',
'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp',
'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf',
'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf',
'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
使用模块:
模块搜索路径:在使用import语句加载某模块时,python解释器会先以该模块的名称搜索内置模块,第二步再去找sys.path所存放的模块搜索路径。
通常sys.path将环境变量PYTHONPATH进行初始化,它由列表组成,元素由相关路径组成,以字符串表示,包含:
执行python文件所在的目录。如果是空字符串“"”,表示当前路径未加入,只要使用python解释器解释执行某个文件就会自动加入
安装软件的默认路径
python的标准函数库
例:借助sys模块的属性path,认识模块搜索路径究竟加载了哪些
>>> import sys
>>> sys.path
['', 'D:\\python3.7.4\\Lib\\idlelib', 'D:\\python3.7.4\\python37.zip', 'D:\\python3.7.4\\DLLs',
'D:\\python3.7.4\\lib', 'D:\\python3.7.4', 'D:\\python3.7.4\\lib\\site-packages']
使用append()方法加入路径:python解释器会在PYTHONPATH环境变量所提供的路径中寻找.py或.pyc模块文件。如果要加入某个路径,可用append()方法
例:
import sys
sys.path.append('D:\\Python\CH08') #append()方法原是列表对象添加元素的方法,要提供完整的路径才会加入,加入成功后即可成为path列表的最后一个元素
自定义模块:要存储范例的路径已经加入sys.path的模块搜索路径才能以import语句导入,否则就会ImportError错误
__name__属性:每个模块都有__name__属性,以字符串存放模块名称,如果直接执行某个.py文件,__name__属性就会被设为__main__名称,表示它是主模块。
如果使用import语句来导入此文件,属性__name__就会被设置成模块名称
reload()函数:
使用import语句加载模块时进行“路径搜索”的过程。import或者from/import语句会在第一次导入模块时所执行模块中的程序代码,
就算以import语句重复加载同一个模块,也不会使得模块中的程序代码被重复执行多次。
原因:python解释器通常分两部分进行处理
1.先寻找“已加载模块”列表中是否有此模块。如果找不到此模块,就按“路径搜索”注意寻找,找到要执行的模块之后,
会创建模块对象并把它记录在“已加载模块的列表内
2.根据import语句加载模块所产生的命名空间,逐一引用所指向的对象
加载模块的探知:配合内置函数len(),用sys模块的属性modules来探查
例:
>>> import sys
>>> len(sys.modules) #以数值返回,此值视系统而定
164
已知使用import语句只会在第一次导入模块时执行模块中的程序代码,但有时需要python解释器运行情况下再次加载模块并重新执行模块文件,可用reload()方法
语法:importlib.reload(module)
说明:module:要重新加载的模块
注意:使用reload()方法时必须要先导入importlib模块(3.4(含)之后的版本,3.4之前的版本要先导入imp模块)
认识函数库:
常用模块:math模块:提供数学方法,cmath则是以复数为处理对象,可以随机产生数值的是random模块
pprint模块:更具阅读性
datetime模块:提供日期
date模块:提供时间
calender模块:提供日历
random模块提供的方法:
choice(seq):从序列项目中随机挑选一个
例:
import random
lst = [78, 56, 90, 14, 67, 99]
print(random.choice(lst))
输出结果:56
randrange(start, stop[, step]):按指定范围,以step为递增的步长来获取一个随机数
例:
import random
print(random.randrange(10,99,3))
输出结果:82
sample(population, k):序列项目随机挑选元素并以列表返回
例:
import random
lst = [78, 56, 90, 14, 67, 99]
print(random.sample(lst, 4))
输出结果:[99, 67, 90, 78]
shuffle(x[,random]):将序列项目重新洗牌(shuffle)
例:
from random import *
lst = [78, 56, 90, 14, 67, 99]
shuffle(lst)
print(lst)
输出结果:[67, 90, 14, 56, 78, 99]
seed(a=None, version=2):初始化随机数的生产器,初始化伪随机数生成器。如果未提供a或者a=None,则使用系统时间为种子。如果a是一个整数,则作为种子。
uniform(a,b):用于生成一个指定范围内的随机浮点数
例:
import random as rd
print(rd.uniform(10,18))
输出结果:16.754102918070508
pprint模块:让输出的数据更具有阅读性
pprint():将数据以数据流方式输出
语法:pprint(object, stream = None, indent = 1, width = 80, depth = None, *, compact = False)
说明:object:要输出内容的对象,必要参数 stream:按标准数据流进行输出,选项参数
indent:选项参数,默认值为1,设置缩排时要配合改变的栏宽才能看出效果 width:每行的栏宽,默认值是80个字符,选项参数
depth:决定输出项目,默认值是None时会全部输出,选项参数
compact:选项参数,默认值为False,是以整体为考虑的,若为True,则以个别项目为格式化的依据
例:
from pprint import pprint as pr
dt = {'Marry Hansen':(1198,'Hangzhou','Female'), 'Bernard Webber':(1992, 'Shanfhai','Male'), 'Charles Nickerson':(1998,'Hangzhou','Male')}
print(dt)
输出结果:{'Marry Hansen': (1198, 'Hangzhou', 'Female'), 'Bernard Webber': (1992, 'Shanfhai', 'Male'), 'Charles Nickerson': (1998, 'Hangzhou', 'Male')}
pr(dt)
输出结果:
{'Bernard Webber': (1992, 'Shanfhai', 'Male'),
'Charles Nickerson': (1998, 'Hangzhou', 'Male'),
'Marry Hansen': (1198, 'Hangzhou', 'Female')}
pr(dt, width=60)
输出结果:
{'Bernard Webber': (1992, 'Shanfhai', 'Male'),
'Charles Nickerson': (1998, 'Hangzhou', 'Male'),
'Marry Hansen': (1198, 'Hangzhou', 'Female')}
pr(dt, width=80, indent=3)
输出结果:
{ 'Bernard Webber': (1992, 'Shanfhai', 'Male'),
'Charles Nickerson': (1998, 'Hangzhou', 'Male'),
'Marry Hansen': (1198, 'Hangzhou', 'Female')}
pr(dt, width=40, depth=1) #depth = 1时只显示key值,value会被隐藏
输出结果:
{'Bernard Webber': (...),
'Charles Nickerson': (...),
'Marry Hansen': (...)}
pr(dt, width=40, depth=2)
输出结果:
{'Bernard Webber': (1992,
'Shanfhai',
'Male'),
'Charles Nickerson': (1998,
'Hangzhou',
'Male'),
'Marry Hansen': (1198,
'Hangzhou',
'Female')}
pr(dt, width=40, depth=2, compact=True) #表示对象的value会根据width=40来决定是否换行
输出结果:
{'Bernard Webber': (1992, 'Shanfhai',
'Male'),
'Charles Nickerson': (1998, 'Hangzhou',
'Male'),
'Marry Hansen': (1198, 'Hangzhou',
'Female')}
PrettyPrinter():PrettyPrinter类的构造函数
pformat():提供格式化效果
语法:pformat(object, indent = 1, width = 80, depth = None, *, compact = False)
说明:object:要输出内容的对象,必要参数
indent:选项参数,默认值为1,设置缩排时要配合改变的栏宽才能看出效果 width:每行的栏宽,默认值是80个字符,选项参数
depth:决定输出项目,默认值是None时会全部输出,选项参数
compact:选项参数,默认值为False,是以整体为考虑的,若为True,则以个别项目为格式化的依据
处理日期和时间的模块:
time: 获取时间戳(timestamp):表示一个绝对时间,通常从某个时间点开始以秒数计算。特别的是这是Unix时间,从1970年1月1日算起,这个值称为epoch
time模块可用来获取当前时间,会以世界标准时间(UTC或者GMT)为准,辅以夏令时间(DST)
struct_time创建的时间结构
索引值 属性 值/说明
0 tm_year 1993,公元年份
1 tm_mon range[1,12],1-12月
2 tm_mday range[1,31],月天数1-31天
3 tm_hour range[0,23],时数0-23
4 tm_min range[0,59],分,0-59
5 tm_sec range[0,59],秒,0-59
6 tm_wday range[0,6],周0-6,0开始是星期一
7 tm_yday range[1,365],天数,一年的天数1-365
8 tm_isdst 0、-1、1表示是否是夏令时间
time():以浮点数返回自1970年1月1日之后的秒数值
例:
import time
seconds = time.time()
print(seconds)
输出结果:1567932987.3167605
sleep(sec):让线程暂时停止执行的秒数
asctime([t]):以字符串返回当前的日期和时间,由struct_time转换
例:
import time
print(time.asctime())
输出结果:Sun Sep 8 17:08:13 2019
ctime([secs]):以字符串返回当前的日期和时间,由epoch转换获取
例:
import time
print(time.ctime(seconds))
输出结果:Sun Sep 8 16:57:26 2019
gmtime():获取UTC日期和时间,可用list转换成数字
例:
import time
print(time.gmtime())
print(list(time.gmtime()))
输出结果:
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=8, tm_hour=9, tm_min=11, tm_sec=8, tm_wday=6, tm_yday=251, tm_isdst=0)
[2019, 9, 8, 9, 11, 8, 6, 251, 0]
localtime():获取本地时间和日期,可用list转换成数字
例:
import time
print(time.localtime())
print(tuple(time.localtime()))
输出结果:
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=8, tm_hour=17, tm_min=12, tm_sec=54, tm_wday=6, tm_yday=251, tm_isdst=0)
(2019, 9, 8, 17, 12, 54, 6, 251, 0)
strftime():将时间格式化,可将获取的时间(以struct_time返回)配合格式化形式以字符串方式来返回时间
语法:strftime(format[, t])
说明:format是格式化字符串,参数t可配合gmtime()或localtime()方法来获取时间
时间值转换的指定形式
时间属性 转换指定格式 说明
%y 以两位数表示年份00~99
年 %Y 以4位数表示年份0000-9999
%j 一年的天数001-365
%m 月份01-12
月 %b 简短月份名称,Ex:Apr
%B 完整月份名称,Ex:April
日期 %d 月份的某一天1-31
时 %H 24小时制,0-23
%I 12小时制,01-12
分 %M 分钟00-59
秒 %S 秒数,00-59
%a 简短星期名称
%A 完整星期名称
星期 %U 一年的周数00-53,由周日开始
%W 一年的周数00-53,由周一开始
%w 星期0-6,星期第几天
时区 %Z 当前时区的名称
%c 本地日期和时间,年/月/日 时:分:秒
其他 %p 本地时间所加入的AM或PM
%x 本地对应的日期,以年/月/日表示
%X 本地对应的时间,以时:分:秒表示
例:
>>> from time import strftime, localtime
>>> print(strftime('%Y-%m-%d %H:%M:%S', localtime()))
2019-09-08 18:04:45
>>> print(strftime('%Y-%m-%d 第%W周', localtime()))
2019-09-08 第35周
>>> print(strftime('%Y-%m-%d 第%j天', localtime()))
2019-09-08 第251天
>>> print(strftime('%c', localtime()))
Sun Sep 8 18:05:04 2019
>>> print(strftime('%X', localtime()))
18:05:11
strptime():按照指定格式返回时间值,会将已格式化的时间值以struct_time返回
语法:strptime(string[,format])
说明:string:想要指定格式的日期和时间,以字符串表示,format:格式化字符串
例:
>>> from time import strptime
>>> tm = '2019-09-08 18:04:45'
>>> strptime(tm,'%Y-%m-%d %H:%M:%S') #strptime()方法当第二个参数指定的格式无法对应第一个参数的时间和日期时会报错
time.struct_time(tm_year=2019, tm_mon=9, tm_mday=8, tm_hour=18, tm_min=4, tm_sec=45, tm_wday=6, tm_yday=251, tm_isdst=-1)
datetime:用来处理时间和日期
两个常数:datetime.MINYEAR:表示最小年份,默认值是MINYEAR = 1
datetime.MAXYEAR:表示最大年份,默认年份是MAXYEAR = 9999
相关类:
date类:用来处理日期问题,与年月日有关
time类:以时间来说可能是某个特定日期的某个时段,所以包含时、分、秒、微秒
datetime:包含日期和时间,因此和date、time类有关的都包含在内
timedelta:表示时间的间隔,可用来计算两个日期、时间的间隔
date类:用来表示日期
构造函数语法:date(year, month, day)
说明:date()构造函数包含年月日三个参数,每个都不能省略,year的范围是1-9999,month的范围是1-12,day的范围根据year和month来定
例:
from datetime import date
print(date(2019, 9, 8))
输出结果:2019-09-08
date类常用的属性和方法(类方法):
day:返回整数天数
year:返回年份
month:返回月份
today():无参数,返回当前的日期
fromdinal(ordinal):根据天数返回年、月、日
fromtimestamp(timestamp):参数配合time.time()可返回当前的日期
date对象常用的属性和方法:
ctime():以字符串返回“星期 月 日 时:分:秒 年”
replace(y,m,d):重新设置参数中年、月、日来新建日期
weekday():返回星期值,索引值0表示周一
isoweekday():返回星期值,索引值为1时表示周一
isocalendar():返回元组对象,如year,month、day
isoformat():以字符串返回其格式,如YYYY-MM-DD
strftime():将日期格式化
timetuple():返回time.struct_time的时间结构
time类:处理组成时间的时、分、秒、微秒
构造函数语法:time(hour = 0, minute = 0, second = 0, microsecond = 0, tzinfo = None)
说明:time()构造函数默认值均为0,也可根据实际去设置值,tzinfo为时区信息
例:
from datetime import time
print(time())
print(time(hour = 20, second=33))
输出结果:
00:00:00
20:00:33
replace()方法:
语法:replace([hour[, minute[, second[, microsecond[, tzinfo]]]]])
例:
from datetime import time
tm = time(15, 20, 30) #构造函数指定时分秒
print(tm.replace(hour=17))
输出结果:17:20:30
datetime类:datetime模块提供了另一个对象方法datetime,使用它可将日期和时间组合在一起,或者用来表示特定的时间
构造方法语法:datetime(year, month, day, hour = 0, minute = 0, second = 0, microsecond = 0, tzinfo = None)
说明:表示参数中的年月日必须指定,与时间有关的参数由于采用了默认值,因此可弹性选择
例:
from datetime import datetime, date
print(datetime(2019, 9, 8)) #只有日期
输出结果:2019-09-08 00:00:00
print(datetime(2019,9,8,hour=20)) #日期/时间
输出结果:2019-09-08 20:00:00
print(datetime(2019,9,8,20,15,37)) #日期时间都有
输出结果:2019-09-08 20:15:37
datetime类方法:
today():获取今天的日期和时间,等同于datetime,fromtimestamp(time.time())
例:
from datetime import datetime
d1 = datetime.today()
d2 = datetime(2019, 9, 10)
dr = d2 - d1 #datetime类允许允许设置两个日期再相减,得到的值用days属性转换成天数
print(dr.days, '天')
输出结果:1天
now(tz = None):获取当前的系统和时间
例:
from datetime import datetime
now = datetime.now()
print(now)
输出结果:2019-09-08 20:20:22.954725
print(now.year, now.month, now.day)
输出结果:2019 9 8
print(now.hour, now.minute, now.second, now.microsecond)
输出结果:20 24 11 824053
utcnow():返回UTC当前的日期和时间
combine():就是把日期和时间结合早一起
语法:combine(date, time)
说明:date:日期对象、 time:时间对象
例:
from datetime import datetime, date, time
dt = date(2019, 9, 8) #日期,取自date构造函数
tm = time(20,47) #时间,取自time构造函数
print(datetime.combine(dt, tm))
输出结果:2019-09-08 20:47:00
print(datetime.combine(dt, tm).strftime('%Y-%m-%d %h:%M:%S'))
输出结果:2019-09-08 Sep:47:00
strptime(date_string, format):格式化datetime类的日期和时间
replace()方法:
语法:replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])
说明:tzinfo:时区信息
例:
from datetime import datetime
dt = datetime.today() #获取今天的日期
dm = dt.replace(day = 10)
print(dm)
输出结果:2019-09-10 20:44:12.543150
d1 = datetime(2018, 3, 12)
print(d1.replace(month=7))
输出结果:2018-07-12 00:00:00
timedelta类:要表示某个特定的日期或用日期进行运算,那么可用timedelta类指定日期或时间值
构造函数语法:timedelta(days = 0, seconds = 0, microseconds = 0, milliseconds = 0, minutes = 0, hours = 0, weeks = 0)
例:
from datetime import datetime, timedelta
d1 = timedelta(days=3, hours=6)
d2 = timedelta(hours=3.2)
dr = d1 + d2 #日期进行相加
print(dr.days, '天')
输出结果:3 天
print('9.2时 = ', dr.seconds, '秒') #输出秒数
输出结果:9.2时 = 33120 秒
print('3天9.2时 = ', dr.total_seconds(), '秒') #将天数和时间全都转换成秒数
输出结果:3天9.2时 = 292320.0 秒
例:利用timedelta的特性进行日期和时间的加减乘除运算
from datetime import datetime, timedelta
d1 = datetime(2019, 9, 8)
print('日期:', d1 + (timedelta(days=7)))
d2 = datetime(2020, 6, 3)
d3 = timedelta(days=105)
dt = d2 - d3 #将两个日期进行相减
print('日期二:', dt.strftime('%Y-%m-%d'))
print('以年、周、星期返回', dt.isocalendar())
输出结果:
日期: 2019-09-15 00:00:00
日期二: 2020-02-19
以年、周、星期返回 (2020, 8, 3)
calender:获取日历,如显示整个年份的日期或某个年份的日历
calendar()方法:
语法:calenda(year, w = 2, l = 1, c = 6, m = 3) #使用calender()方法要加print()方法才可输出
prcal(year, w = 0, l = 0, c = 6, m = 3) #不需使用print()函数直接输出日历
说明:year:用于指定公元年份 w:显示日期的栏宽(或字段宽度) l:表示行高 c:表示两个月份之间的宽度
m:表示每行要输出的月份,默认值是3
例:
import calendar
print(calendar.calendar(2019))
输出结果:
2019
January February March
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 1 2 3 1 2 3
7 8 9 10 11 12 13 4 5 6 7 8 9 10 4 5 6 7 8 9 10
14 15 16 17 18 19 20 11 12 13 14 15 16 17 11 12 13 14 15 16 17
21 22 23 24 25 26 27 18 19 20 21 22 23 24 18 19 20 21 22 23 24
28 29 30 31 25 26 27 28 25 26 27 28 29 30 31
April May June
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7 1 2 3 4 5 1 2
8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9
15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16
22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23
29 30 27 28 29 30 31 24 25 26 27 28 29 30
July August September
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 7 1 2 3 4 1
8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8
15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15
22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22
29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29
30
October November December
Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su
1 2 3 4 5 6 1 2 3 1
7 8 9 10 11 12 13 4 5 6 7 8 9 10 2 3 4 5 6 7 8
14 15 16 17 18 19 20 11 12 13 14 15 16 17 9 10 11 12 13 14 15
21 22 23 24 25 26 27 18 19 20 21 22 23 24 16 17 18 19 20 21 22
28 29 30 31 25 26 27 28 29 30 23 24 25 26 27 28 29
30 31
import calendar
calendar.prcal(2019)
输出结果:等同于print(calendar.calendar(2019))
setfirstweekday():输出日历时通常以星期一为一周的开始,若想修改为其他天为开始可用此方法
语法:setfirstweekday(weekday)
说明:weekday表示星期名称,由MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
例:使用setfirstweekday()方法指定日历第一天是周日,再用pracal()输出年例
import calendar
calendar.setfirstweekday(calendar.SUNDAY)
calendar.prcal(2019, c = 3, m = 4)
输出结果:
2019
January February March April
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 1 2 1 2 1 2 3 4 5 6
6 7 8 9 10 11 12 3 4 5 6 7 8 9 3 4 5 6 7 8 9 7 8 9 10 11 12 13
13 14 15 16 17 18 19 10 11 12 13 14 15 16 10 11 12 13 14 15 16 14 15 16 17 18 19 20
20 21 22 23 24 25 26 17 18 19 20 21 22 23 17 18 19 20 21 22 23 21 22 23 24 25 26 27
27 28 29 30 31 24 25 26 27 28 24 25 26 27 28 29 30 28 29 30
31
May June July August
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 1 1 2 3 4 5 6 1 2 3
5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10
12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17
19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24
26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30 31
30
September October November December
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7 1 2 3 4 5 1 2 1 2 3 4 5 6 7
8 9 10 11 12 13 14 6 7 8 9 10 11 12 3 4 5 6 7 8 9 8 9 10 11 12 13 14
15 16 17 18 19 20 21 13 14 15 16 17 18 19 10 11 12 13 14 15 16 15 16 17 18 19 20 21
22 23 24 25 26 27 28 20 21 22 23 24 25 26 17 18 19 20 21 22 23 22 23 24 25 26 27 28
29 30 27 28 29 30 31 24 25 26 27 28 29 30 29 30 31
month():输出指定年份的某月日历,需要配合print()使用才能输出
prmonth():输出指定年份的某月日历,直接输出
语法:month(theyear, themonth, w = 0, l = 0)
prmonth(theyear, themonth, w = 0, l = 0)
说明:theyear:指定公元年份,themonth:指定月份,w:设置栏宽,l:设置行高
例:
import calendar
print(calendar.month(2019, 9))
输出结果:
September 2019
Mo Tu We Th Fr Sa Su
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
import calendar
calendar.prmonth(2019, 6, w = 3, l = 2)
输出结果:
June 2019
Mon Tue Wed Thu Fri Sat Sun
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
处理闰年的问题:
isleap(year):判断输入年份是否是闰年,参数是year,以布尔值返回结果,如果是闰年,就返回True
例:
import calendar as ca
print(ca.isleap(2016))
输出结果:True
leapdays(y1, y2):判断两个年份之间有几个闰年
例:
import calendar as ca
print(ca.leapdays(2000, 2016))
输出结果:4
内置函数(部分)
内置函数(BIF)zip():使用zip()函数可对二维列表进行压缩或者解压的操作,使用zip()函数时,
会从左到右按元组(tuple)形式读取,根据其每列所读确定长度
语法:zip(*iterable)
说明:将每个可迭代的元素予以聚合之后重新产生一个可迭代器
*运算符的作用是将列表压缩
例:
x = [22, 24, 26]
y = [12, 56, 89]
print(list(zip(x, y)))
输出结果:[(22, 12), (24, 56), (26, 89)]
print(zip(x, y))
输出结果:<zip object at 0x033D3080>
注:要以tuple()或者list()来转换zip()函数的可迭代对象,未用tuple()或者list()开转换时只会输出zip object
x = [22, 24, 26, 67]
y = [12, 56, 89]
print(list(zip(x, y)))
输出结果:[(22, 12), (24, 56), (26, 89)]
字符串
字符串的创建方法:
(1).借助标识符规则给予名称:
wordA = '' #空字符串
wordB = 'B' #单一字符串
wordC = 'python'
(2)。使用内置函数str()来获取字符串
str() #输出空字符串
str(123) #将123转换成字符串
注:字符串具有不可变的特性,将两个变量指向同一个字符串,表示引用同一个字符串,id()函数会返回相同的标识符(即两者指向同一内存地址)
例:
>>> word = 'helloworld'
>>> data = 'helloworld'
>>> id(word)
67020984
>>> id(data)
67020984
使用内置函数enumerate(iterable, start = 0)给字符串添加索引
enumerate(iterable, start = 0)
itarable:可迭代的,字符串、列表、元组都适用
start:设置索引编号起始值,默认是0
例:
>>> word = 'hello'
>>> list(enumerate(word))
[(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]
>>> week = ['mon','tus','wed','tusd','fri','sat','sun']
>>> list(enumerate(week))
[(0, 'mon'), (1, 'tus'), (2, 'wed'), (3, 'tusd'), (4, 'fri'), (5, 'sat'), (6, 'sun')]
>>> list(enumerate(week,1))
[(1, 'mon'), (2, 'tus'), (3, 'wed'), (4, 'tusd'), (5, 'fri'), (6, 'sat'), (7, 'sun')]
字符切片:字符串的字符具有顺序性,使用[]运算符来提取字符串中的单个或某个范围内的子字符串
s[n]:按指定索引值获取序列的某个元素
s[n,m]:从索引值n到m-1来获取若干元素(含左不含右)
s[n:]:从索引值n开始到最后一个元素
s[:m]:从索引值0开始到索引值m-1结束
s[:]:表示会复制一份序列元素
s[::-1]:将整个序列元素反转
语法: sequence[start : ]
sequence[start : end]
sequence[start : end : step](step的正负值表示不同方向,step为正,表示从左向右,step为负,表示从右向左)
注:索引值从左向右从0开始,从右向左从-1开始
使用join()方法来连接字符串时必须是可迭代对象
对齐字符串的相关方法:
center(width[,fillchar]):增加字符串宽度,字符串居中,两侧补空格符
ljust(width[,fillchar]):增加字符串宽度,字符串靠左对齐,右侧补空格符
rjust(width[,fillchar]):增加字符串宽度,字符串靠右对齐,左侧补空格符
zfill(width):字符串左侧补0
expandtabs([tabsize]):按tab键时转成一个或多个空格符
partition(sep):字符串分割成三部分,seq前、seq、seq后
splitlines([keepeds]):按照符号分割字符串为序列元素,keepends = True保留分割的符号
格式化字符串:
(1).%运算符配合“转换指定形式”产生“格式字符串”
语法:格式字符串%对象
格式字符串:由于本身是字符串,所以前后要加单引号或双引号。字符串中以%格式运算符开头,标注转换指定形式是数值或字符串
对象:配合转换指定形式,可以是变量、数值、字符串
形式如下:
%% 输出数据时显示%符号
%d,%i 以十进制输出数据
%f 将浮点数以十进制输出
%e,%E 将浮点数以十进制和科学计数法输出
%x,%X 将整数以十六进制输出
%o,%O 将整数以八进制输出
%s 使用str()函数输出字符串
%c 使用字符方式输出
%r 使用repr()函数输出
例:
>>> word = 'python'
>>> print('i love %s'%word) #i love %s中的%s是格式字符串,表示要导入一个字符串,后方的%word会被带入而输出i love python
i love python
>>> print('%s was conceived in the late %ds'%(word, 1980)) # %s ... %d表示要导入两个字符串,所以%运算符要配合括号()带入%(word, 1980)
python was conceived in the late 1980s
(2).内置函数format()配合标志、栏宽、精确度和转换的指定形式来输出格式数据
语法:%[flag][width][.precision]要转换的指定形式
flag:配合相关字符输出格式,下面的format()函数的标志
width:栏宽,设置需要输出数据的宽度
precision:以浮点数输出可指定其小数位数
例:
>>> print('%04d'%25) #输出四位整数,左侧补0
0025
>>> import math
>>> print('PI=',math.pi)
PI= 3.141592653589793
>>> print('PI = %.4f'%math.pi) #输出浮点数时,保留四位小数,四舍五入其他位数
PI = 3.1416
语法:format(value[,format_spec])
value:想要格式化的数值或字符串
format_spec:就是格式字符串,根据其指定格式,同样用标志、栏宽和精确度进行搭配(栏宽(字段宽度):字符所占的宽度;精确度:使用浮点数时可以设置输出的小数位数)
format()函数的标志:
'#' 配合十六进制、八进制进行转换时,可在前方补0
'0' 数值前补0
'-' 靠左对齐,若与0同时使用时,会优于0
'' 会保留一个空格
> 靠右对齐
< 靠左对齐
例:
>>> word = 'hello'
>>> format(word, '<10s') #设置栏宽为10,靠左对齐
'hello '
>>> format(word, '>10s') #设置栏宽为10,靠右对齐
' hello'
注:使用对齐格式时,必须加入栏宽设置才能看出靠左靠右的对齐作用
>>> number = 12.347
>>> format(number, '<12f') #设置栏宽为12,靠左对齐
'12.347000 '
注:把十进制数转换为十六进制数或八进制数时,标志'#'字符可在前方(左侧)补0
>>> '%x %#x'%(124, 124) #转换为16进制数
'7c 0x7c'
>>> '%-8d %08d'%(124, 124) #靠左对齐,前方补0
'124 00000124'
(3).创建字符串对象配合format()方法,使用大括号{}扩住字段名(或成为栏名)进行替换,{}的索引编号从0开始
str.format()方法
例:
>>> '{0}{1}'.format('PI = ', 3.14156)
'PI = 3.14156'
语法:{字段名}
字段名(或栏名):大括号里可以使用位置和关键字传递参数
位置参数使用索引编号,从0开始;关键字搭配变量。无论是哪种参数都可交替使用
关键字参数要以“变量 = 变量值”带入大括号{}中
例1:format()方法配合字段名的使用
>>> '{prog} was conceived in the late {year}s'.format(prog = 'python', year = 1980)
'python was conceived in the late 1980s'
例2:format()方法配合一个位置参数和一个关键字来使用
>>> 'The {prog} was {0}'.format(34, prog = 'python')
'The python was 34'
例3:format()方法配合属性使用
语法:{字段名.属性}
属性:选项参数,是位置和关键字参数的第3种选择,用 . 来获取某个对象的属性
例:>>> import math
>>> 'math.pi = {0.pi}'.format(math)
'math.pi = 3.141592653589793'
语法:{字段名 ! 转换};以 ! 作为转换的开头,后面可以使用BIF的s(str)、r(repr)、a(ascii)来获取字符串
例:
>>> from decimal import Decimal
>>> '{0} {0!s} {0!r} {0!a}'.format(Decimal(28.5))
"28.5 28.5 Decimal('28.5') Decimal('28.5')"
#{0}输出字符串28.5;{0!s}是将数值转换为字符串;{0!r}是将Decimal('28.5')转换为字符串对象来输出
语法:{字段名 : format-spec}
format()方法转换的指定格式
fill 可填补任何字符,但不包括大括号
align 以4种字符进行对齐,<为靠左;>为靠右;=为填补;^为居中
sign 使用+ - 或 空格 ,同%格式字符串
# 用法与%格式运算符相同
0 用法与%格式运算符相同
width 栏宽或字段宽度
, 千位符号,就是每3位数就加上逗号
.precision 精确度,用法与%格式运算符相同
typecode 用法与%格式运算符几乎相同
例:
import math
print('PI = {0.pi}'.format(math)) # 输出PI的值
print('PI = %10.4f' % (math.pi)) #输出思4位小数
print('PI = {0:010f}'.format(math.pi)) # 前方补0,栏宽为10
radius = (math.pi) * 26 ** 2 # 计算圆面积
# 圆面积加千位逗号
print('PI = {0:.4f}\n 圆面积 = {1:, .3f}'.format(math.pi, radius))
area = int(radius) #转换为整数
print('以十进制、十六进制、二进制输出:')
print('圆面积 = {0:d}, {0:#x}, {0:#b}'.format(area))
print('靠右 = {0:*>10d}'.format(area)) #*字符填满
print('居中 = {0:*^10d}'.format(area))
总体略叙
python 学习笔记
python 精准缩进,注释两种,
单行#这是一条注释语句
多行""" 这是多行注释 """
1.在使用变量前,要对其赋值
2.变量名可以包括字母、数字、下划线,但变量名不能以数字开头
3.区分大小写
4.字符串中出现 '' 、 "" 、 \ 时要用转义字符对引号进行转义从而打印输出
如:'let\'s go!',也可以用str = r'C":\user\nihao'来将多个\自行添加转义字符
5.isinstance(a,str)用来判断a是否是str类型,可用Type(a)内置函数来获取a的数据类型
6.条件表达式(三元操作符)
语法:x if 条件 else y 条件成立则为x 否则是y
x,y = 4,5
if x < y:
small = x
else:
small = y
以上可改为:
small = x if x < y else y
7.断言assert 当关键字后边条件为假时,程序自动崩溃并抛出AssertionError异常。
可用assert在程序中植入检查点,当需要确保程序中的某个条件一定为真时才能让程序正常工作时可用assert
例: assert 3 > 4抛出异常
8.for循环: 语法:for 目标 in 表达式 :
循环体
例:str = 'helloword'
for i in str:
print(i, end=' ')
输出结果是:h e l l o w o r d
memeber = ['xiaoming','xiaolan','小弘']
for each in memeber:
print(each, len(each))
输出结果是:xiaoming 8
xiaolan 7
小弘 2
9.range( [start,] stop[, step=1]) 该BIF有三个参数,其中用括号括起来的两个表示这两个参数是可选的
step=1表示第三个参数的默认值是1,即每隔几个数,例如range(0, 5, 1)表示 01234, range(0,5,2)表示 0 2 4,第一个参数默认是0
作用:生成一个从start参数的值开始到stop参数的值结束的数字序列,但是不包含stop,start默认是0
例: for i in range(5):
print(i)
输出结果: 0
1
2
3
4
for i in range(0,8):
print(i)
输出结果: 0
1
2
3
4
5
6
7
for i in range(0,10,2):
print(i)
输出结果: 0
2
4
6
8
10.列表: memeber = ['xiaoming','xiaolan','小弘', 88]
列表元素可以是不同数据类型
列表末尾追加一个元素整数1:
memeber.append(1) 表示在member末尾添加一个整数1
列表末尾追加多个元素:extend() 原理:用一个列表扩展另一个列表
member.extend([1,2])表示在member末尾添加1和2
列表在指定位置添加元素:insert(1,'nihao'),不会覆盖原数值,列表会自动扩展长度,剩下的元素顺移一个位置
memeber.insert(1,'nihao')表示在member的下标为1的位置添加nihao
列表元素删除:remove()
member.remove('xiaoming'):把xiaoming从列表中移除
列表删除元素:del
del memeber[1] 表示把member[1]元素删除,即删除xiaolan
del member 表示把member列表删除
列表删除元素:pop()
member.pop()默认删除列表最后一个元素,返回删除的元素
member.pop(1)删除列表下标为1的元素
列表分片:获取多个元素
member[1:3]获取列表下标为1到3的元素,其中包含1不包含3,返回一个子列表
member[:]复制该列表,返回一个与该列表元素相同的列表
列表是否包含某元素a: a in memeber 若a存在memeber则返回True,否则返回False
列表元素个数:memeber.count() 返回列表的元素个数
列表元素所在位置:memeber.index(a),返回元素a所在的下标
列表翻转:memeber.reverse()返回一个新的列表,列表元素是原列表元素翻转后的顺序
列表排序:member.sort() 返回一个新列表,列表元素是原列表从小到大排序后的元素顺序
list.sort(cmp=None, key=None, reverse=False)
cmp -- 可选参数, 如果指定了该参数会使用该参数的方法进行排序。
key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse -- 排序规则,reverse = True 降序, reverse = False 升序(默认)。
返回值:该方法没有返回值,但是会对列表的对象进行排序。
以下实例展示了 sort() 函数的使用方法:
实例
aList = ['Google', 'Runoob', 'Taobao', 'Facebook'];
aList.sort();
print ("List : ", aList)
以上实例输出结果如下:
List : ['Facebook', 'Google', 'Runoob', 'Taobao']
以下实例降序输出列表:
# 列表
vowels = ['e', 'a', 'u', 'o', 'i']
# 降序
vowels.sort(reverse=True)
# 输出结果
print('降序输出:', vowels)
以上实例输出结果如下:
降序输出: ['u', 'o', 'i', 'e', 'a']
以下实例演示了通过指定列表中的元素排序来输出列表:
# 获取列表的第二个元素
def takeSecond(elem):
return elem[1]
# 列表
random = [(2, 2), (3, 4), (4, 1), (1, 3)]
# 指定第二个元素排序以升序进行排序
random.sort(key=takeSecond)
# 输出类别
print('排序列表:', random)
以上实例输出结果如下:
排序列表:[(4, 1), (2, 2), (1, 3), (3, 4)]
12.数据交换:a,b = b,a
13.元组:一经定义则元素不可改变,与列表使用相似
创建和访问一个元组:tuple1 = (1,2,3,4,5,6,)
空元组:tuple = ()
只含一个元素的元组:tuple = (1,) 必须含有 "," 否则不认为是元组
8个元素为8的元组:tuple = 8 * (8,)
5个元素为6的元组:tuple2 = 5*(6,)
元组切片:tuple2 = tupple[:],与列表相同
元组添加:temp = ('小弘','小明',1,2),值不会被覆盖掉,插入位置之后的元素顺移一位(通过元组的部分复制后添加新的元素重新组合成一个元组)
temp = temp[:2] + ('小兰',) + temp[2:] 在下标为2的位置上添加元素小兰
元组删除:del temp
14.字符串: capitalize() 把字符串的第一个字符改为大写
casefold() 把整个字符串的所有字符改为小写
center(width) 将字符串居中,并使用空格填充至长度width的新字符串
count(sub[,start[,end]]) 返回sub在字符串里出现的次数,start和end作为参数表示范围,可选
encode(encoding='utf-8',errors='strict') 以ecoding指定的编码格式对字符串进行编码
startwith(prefix[,start[,ebd]]) 检查字符串是否以prefix开头,如果是返回True否则返回False
endswith(sub[,start[,end]]) 检查字符串是否以sub子字符串结束,如果是返回True否则False
expandtabs([tabsize=8]) 把字符串中的tab符号(\t)转换为空格,如不指定参数,则默认空格数是tabsize=8
find(sub[,start[,end]]) 检测sub是否包含在字符串中,如果有则返回索引值,否则返回-1,start和end表示参数范围,可选
rfind(sub[,start[,end]]) 与find类似,不过从右边开始查找
index(sub[,start[,end]]) 和find()方法一样,但是如果sub不在字符串中会产生一个异常
rindex(sub[,start[,end]]) 与index()类似,不过从右边开始
isalnum() 如果字符串至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False
isalpha() 如果字符串至少有一个字符并且所有字符都是字母则返回True,否则返回False
isdecimal() 如果字符串只包含十进制数字则返回True,否则返回False
isdigit() 如果字符串只包含数字则返回True,否则返回False
isupper() 如果字符串中至少包含一个区分大小写的字符,并且这些字符都是大写,则返回True,否则返回False
islower() 如果字符串中至少包含一个区分大小写的字符,并且这些字符都是小写,则返回True,否则返回False
isnumberic() 如果字符串中只包含数字字符,则返回True否则返回False
isspace() 如果字符串中只包含空格,则返回True否则返回False
title() 返回标题化的字符串(所有单词的首字母大写,其他字母均小写)
istitle() 如果字符串是标题化(所有单词首字母都是大写,其余字母均为小写),则返回True否则返回False
join(sub) 以字符串作为分隔符,插入到sub中所有的字符之间,如原字符串是abc,调用join(1)后字符串变为1a1b1c
ljust(width) 返回一个左对齐的字符串,并用空格填充至长度为width的新字符串
rjust(width) 返回一个右对齐的字符串,并使用空格填充至width的新字符串
upper() 将字符串中所有小写转换成大写
lower() 将字符串中所有大写转换成小写
strip([chars]) 不加参数默认删除字符串前边和后边所有的空格,中间的不删除,chars参数可以定制删除的字符,可选
lstrip() 去掉字符串左边的所有空格
rstrip() 删除字符串末尾的所有空格
partition(sub) 找到子字符串sub,把字符串分成一个3元组(pre_sub,sub,fol_sub),如果字符串中不包含sub则返回('原字符串','','')
rpartition(sub) 与partition()类似,不过从右边开始查找
replace(old,new[,count]) 把字符串中的old子字符串替换为new子字符串,如果count指定,则替换不超过count次
split(sep=None, maxsplit=-1) 不带参数默认是以空格为分隔符切片字符串,如果maxsplit参数有设置,则仅分割maxsplit个子字符串,返回切片后的子字符串拼接的列表
splitlines(([keepends])) 按照“\n”分隔,返回一个包含各行作为元素的列表,如果keepends参数指定,则返回前keepends行
swapcase() 翻转字符串中的大小写
translate(table) 根据table的规则(可以有str.maketrans('a','b')定制)转换字符串中的字符,如str='ssssaaaassss' str.translate(str.maketrans('s','b')),结果是bbbbaaaabbbb
zfill(width) 返回长度为width的字符串,原字符串右对齐,前边用0填充
15.format() 基本语法是通过 {} 和 : 来代替以前的 % 。
format 函数可以接受不限个参数,位置可以不按顺序。
实例
>>>"{} {}".format("hello", "world") # 不设置指定位置,按默认顺序
'hello world'
>>> "{0} {1}".format("hello", "world") # 设置指定位置
'hello world'
>>> "{1} {0} {1}".format("hello", "world") # 设置指定位置
'world hello world'
也可以设置参数:
print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com"))
# 通过字典设置参数
site = {"name": "菜鸟教程", "url": "www.runoob.com"}
print("网站名:{name}, 地址 {url}".format(**site))
# 通过列表索引设置参数
my_list = ['菜鸟教程', 'www.runoob.com']
print("网站名:{0[0]}, 地址 {0[1]}".format(my_list)) # "0" 是必须的
输出结果为:
网站名:菜鸟教程, 地址 www.runoob.com
网站名:菜鸟教程, 地址 www.runoob.com
网站名:菜鸟教程, 地址 www.runoob.com
也可以向 str.format() 传入对象:
实例
class AssignValue(object):
def __init__(self, value):
self.value = value
my_value = AssignValue(6)
print('value 为: {0.value}'.format(my_value)) # "0" 是可选的
输出结果为:
value 为: 6
数字格式化
下表展示了 str.format() 格式化数字的多种方法:
>>> print("{:.2f}".format(3.1415926));
3.14
数字 格式 输出 描述
3.1415926 {:.2f} 3.14 保留小数点后两位
3.1415926 {:+.2f} +3.14 带符号保留小数点后两位
-1 {:+.2f} -1.00 带符号保留小数点后两位
2.71828 {:.0f} 3 不带小数
5 {:0>2d} 05 数字补零 (填充左边, 宽度为2)
5 {:x<4d} 5xxx 数字补x (填充右边, 宽度为4)
10 {:x<4d} 10xx 数字补x (填充右边, 宽度为4)
1000000 {:,} 1,000,000 以逗号分隔的数字格式
0.25 {:.2%} 25.00% 百分比格式
1000000000 {:.2e} 1.00e+09 指数记法
13 {:10d} 13 右对齐 (默认, 宽度为10)
13 {:<10d} 13 左对齐 (宽度为10)
13 {:^10d} 13 中间对齐 (宽度为10)
11 进制
'{:b}'.format(11) 1011
'{:d}'.format(11) 11
'{:o}'.format(11) 13
'{:x}'.format(11) b
'{:#x}'.format(11) 0xb
'{:#X}'.format(11) 0XB
^, <, > 分别是居中、左对齐、右对齐,后面带宽度, : 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。
+ 表示在正数前显示 +,负数前显示 -; (空格)表示在正数前加空格
b、d、o、x 分别是二进制、十进制、八进制、十六进制。
此外我们可以使用大括号 {} 来转义大括号,如下实例:
实例
print ("{} 对应的位置是 {{0}}".format("runoob"))
输出结果为:
runoob 对应的位置是 {0}
16.序列:len(sub) 返回sub的长度
max(sub) 返回sub序列或参数中最大的那个元素,字母按ASII码进行比较
min() 返回序列或餐胡中最小的那个元素
注:使用max() 和min()方法都要保证序列或字符或者元组的数据类型必须是统一的
sun(iterable[,start=0]) 返回序列iterable和可选参数start的总和 参数或序列的数据类型必须一样
sorted() 返回一个新的排序列表,默认是从小到大排序
reversed() 返回一个迭代器对象,可用list(reversed(a))来获取a反转后的元素
enumerate() 枚举,返回一个对象,可用list(enumerate())获取元素
例:number = [11,20,33]
list(enumerate(number))
输出结果为:
[(0, 11), (1, 20), (2, 33)]
zip(a,b) 返回一个对象,用list(zip(a,b))获取元素将a的各个元素与b的各个元素进行打包,只打包到数量少的那个
例:a = [1,2,3,4,5,6]
b = ["x","y","z"]
zip(a,b)
输出结果:
<zip object at 0x0478DCD8>
list(zip(a,b))
输出结果:
[(1, 'x'), (2, 'y'), (3, 'z')]
17.函数:
创建函数:
def MyFirstFunction():
print("这是我第一个创建的函数")
调用函数:MyFirstFunction()
写函数的注释,类似于java的/** */ 在函数体内用 '这是MyFirstFunction的注释' 来进行写注释
函数的变量可以有默认值,如 def MyFirstFunction(name='hello', word='world'):
print(name + word)
MyFirstFunction()
输出结果是: helloworld
MyFirstFunction('小明')
输出结果:小明world
收集参数:def test(*params,exp = 8): #exp = 8表示默认参数是exp = 8
print('参数的长度是:',len(params))
print('第二个参数长度是:',params[1])
test(1,'小明',3,3.14,5)
输出结果:参数的长度是:5
第二个参数长度是:小明
变量作用域:局部变量:只作用于函数体内,只在函数内生效
全局变量:全局访问,但是在函数内修改全局变量时python会自动新建一个同名的局部变量代替
global关键字:在函数体内修改全局变量
内嵌函数:在函数内再创建一个函数
例:def fun():
print('函数1')
def fun2():
print('函数2')
fun2()
fun()
输出结果:函数1
函数2
闭包:如果在一个内部函数里对外部作用域(但不是在全局作用域的变量)进行引用,那么内部函数就会被认为是闭包
例:def FunX(x):
def FunY(y):
return x * y
return FunY
>>> i = FunX(5)
>>> i
<function FunX.<locals>.FunY at 0x032C3A08>
>>> type(i)
<class 'function'>
>>> i(10)
50
#也可像一下方式调用
>>> FunX(5)(10)
50
注:因为FunY()是内部函数,所以在外部不可直接调用FunY()
nonlocal关键字:将内部函数外但是处于外部函数内的局部变量声明为伪全局变量,即内部函数也可访问的全局变量
lambda表达式:用来创建匿名函数,对于一些比较抽象并且整个程序内只执行一两次的函数不必命名可以使用lambda,也可提高代码可读性
例:定义普通函数: def fun(x):
return 2 * x + 1
lambda创建函数:lambda x : 2 * x + 1
#返回一个函数,可用一个值接收在用该函数
g = lambda x : 2 * x + 1
g(5)
输出结果:11
BIF filter()过滤器:filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
注意: Pyhton2.7 返回列表,Python3.x 返回迭代器对象
filter(function, iterable) 参数 function -- 判断函数。 iterable -- 可迭代对象。 返回值 返回列表。
例:>>> filter(None, [1,0,False,True])
<filter object at 0x04910D30>
>>> list(filter(None, [1,0,False,True]))
[1, True]
>>> def odd(x):
return x % 2
>>> temp = range(10)
>>> show = filter(odd, temp)
>>> list(show)
[1, 3, 5, 7, 9]
>>> list(filter(lambda x : x % 2, range(10)))
[1, 3, 5, 7, 9]
BIF map(): 会根据提供的函数对指定序列做映射。
map(function, iterable, ...)
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
返回值
Python 2.x 返回列表。
Python 3.x 返回迭代器。
实例
以下实例展示了 map() 的使用方法:
>>>def square(x) : # 计算平方数
return x ** 2
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
18.递归:性能不高,要设定递归次数,一定要有递归出口
例:
def fact(n):
if n == 1:
return 1
else:
return n*fact(n-1)
number = int(input('请输入数字'))
print(fact(number))
使用迭代获取斐波那契数列第N项值:
#n是第几项
def fab(n):
n1 = 1
n2 = 1
n3 = 1
if n < 1:
print('输入有误')
return -1
while (n-2) > 0:
n3 = n2 + n1
n1 = n2
n2 = n3
n -= 1
return n3
result = fab(4)
if result != -1:
print(result)
输出结果:3
使用递归获取斐波那契数列第N项值:
def fab(n):
if n <1:
print('输入有误,请重新输入!')
return -1
if n == 1 or n == 2:
return 1
else:
return fab(n - 1) + fab(n - 2)
print(fab(6))
输出结果:8
递归与迭代比较:迭代性能比递归高的多。因为递归需要层层调用函数,要不断在内存中开辟新空间存放值,效率低性能慢
汉若塔问题:def hanoi(n,x,y,z):
if n == 1:
print(x,'---->',z)
else:
hanoi(n-1,x,z,y)#将n-1个盘子从x移到y上
print(x,'--->',z) #将最底下的最后一个盘子从x移到z上
hanoi(n-1,y,x,z)#将y上的n-1个盘子移动到z上
n = int(input('请输入汉诺塔的层数'))
hanoi(n,'x','y','z')
请输入汉诺塔的层数4
x ----> y
x ---> z
y ----> z
x ---> y
z ----> x
z ---> y
x ----> y
x ---> z
y ----> z
y ---> x
z ----> x
y ---> z
x ----> y
x ---> z
y ----> z
19.字典(唯一映射类型,相当于java中的map键值对):
例:无字典时:
>>> band = ['李宁','nike','adidas']
>>> slogan = ['一切皆有可能','just do it','impossible is nothing']
>>> print('nike的slogan是:',slogan[band.index('nike')])
nike的slogan是: just do it
使用字典:
dict1 = {'李宁':'一切皆有可能' , 'nike':'just do it' , 'adidas':'impossible is nothing'}
>>> print('nike的slogan是:',dict1['nike'])
nike的slogan是: just do it
dict()函数:
#使用元组创建字典:
dict3 = dict((('F',70),('i',105),('s',115),('h',104)))
>>> dict3
{'F': 70, 'i': 105, 's': 115, 'h': 104}
#使用键值对创建字典:
>>> dict4 = dict(小王八 = '123456',巴西龟='绿毛龟')
>>> dict4
{'小王八': '123456', '巴西龟': '绿毛龟'}
#使用列表追加字典:
>>> dict4['王八犊子'] = '网吧小瘪犊子'
>>> dict4
{'小王八': '123456', '巴西龟': '绿毛龟', '王八犊子': '网吧小瘪犊子'}
当索引不好用时:
fromkeys():创建一个新的字典,参数是键值对,如若不写则默认是None
dicct.fromkeys(S[,v]) -> new dict with keys from S and values equal to v(v defaults to None)
例:
>>> dict1 = {}
>>> dict1.fromkeys((1,2,3))
{1: None, 2: None, 3: None}
>>> dict1.fromkeys((1,2,3),'number')
{1: 'number', 2: 'number', 3: 'number'}
>>> dict1.fromkeys((1,2,3),('one','two','three'))
{1: ('one', 'two', 'three'), 2: ('one', 'two', 'three'), 3: ('one', 'two', 'three')}
#注:value的值只能有一个,一个value值匹配参数列表中所有的k值
#注:不可进行批量修改,如dict1。fromkeys((1,3),'数字')会创建一个新的字典
keys():返回字典键的引用,即获取key的值
例:>>> dict2 = dict.fromkeys(range(10),'你好')
>>> dict2
{0: '你好', 1: '你好', 2: '你好', 3: '你好', 4: '你好', 5: '你好', 6: '你好', 7: '你好', 8: '你好', 9: '你好'}
>>> for i in dict2.keys():
print(i)
输出结果:
0
1
2
3
4
5
6
7
8
9
values():返回value的值
例:>>> for eachValues in dict2.values():
print(eachValues)
输出结果:
你好
你好
你好
你好
你好
你好
你好
你好
你好
你好
items():打印键值对
例:>>> for eachItems in dict2.items():
print(eachItems)
输出结果:
(0, '你好')
(1, '你好')
(2, '你好')
(3, '你好')
(4, '你好')
(5, '你好')
(6, '你好')
(7, '你好')
(8, '你好')
(9, '你好')
get():当未知是否含有该键时使用,可设键对应值的参数,如果字典有该键时,则获取该键所对应的键值对的值,
否则获取设置的value值,如果参数key没有设置对应的value值,则默认为None
例:>>> dict2.get(10)
>>> print(dict2.get(10))
None
>>> dict2.get(10,'木有')
'木有'
>>> dict2.get(9,'木有')
'你好'
in 和 not in:判断key是否在字典中
例:>>> 10 in dict2
False
>>> 9 in dict2
True
>>> 10 not in dict2
True
>>> 9 not in dict2
False
clear():清空字典
例:>>> dict1.fromkeys((1,2,3),'number')
{1: 'number', 2: 'number', 3: 'number'}
>>> dict1.clear()
>>> dict1
{}
copy():前拷贝字典
例:>>> a = {1:'one',2:'two',3:'three'}
>>> b = a.copy() #前拷贝
>>> c = a #赋值
>>> c
{1: 'one', 2: 'two', 3: 'three'}
>>> b
{1: 'one', 2: 'two', 3: 'three'}
>>> a
{1: 'one', 2: 'two', 3: 'three'}
>>> id(a)
66525248
>>> id(b)
16146528
>>> id(c)
66525248
#注:前拷贝地址不同,赋值地址相同
#注:前拷贝是拷贝对象,重新在内存申请空间,赋值是将同一个地址空间赋予多个名字,其中一个改了数据后同一个地址空间的其他值也受到影响
pop():给定一个键弹出一个值,这个值将从字典中移除
例:>>> a = {1: 'one', 2: 'two', 3: 'three'}
>>> a.pop(1)
'one'
>>> a
{2: 'two', 3: 'three'}
popitem():随机弹出一个键值对,因为字典无顺序,所以随机弹出一个键值对
例:>>> a.popitem()
(3, 'three')
>>> a
{2: 'two'}
setdefault():与get()类似,但当找不到key的对应value值时会添加
例:>>> a.setdefault('xiaohong')
>>> a
{2: 'two', 'xiaohong': None}
>>> a.setdefault(5,'five')
'five'
>>> a
{2: 'two', 'xiaohong': None, 5: 'five'}
update():用一个字典映射更新另一个字典
例:>>> b = {'xiaohong':'小弘'}
>>> a.update(b)
>>> a
{2: 'two', 'xiaohong': '小弘', 5: 'five'}
20.集合(唯一性,数据不重复,无序,无索引)
创建集合:使用{}:num1 = {1,2,3,4,5}
set(): >>> set1 = set([1,2,3,4,4,5])
>>> set1
{1, 2, 3, 4, 5}
引申:去掉列表中重复数据:
传统方法: num1 = [1,2,3,4,5,5,3,1,0]
temp = []
for each in num1:
if each not in temp:
temp.append(each)
print(temp)
输出结果:[1, 2, 3, 4, 5, 0]
使用集合:num2 = [1,2,3,4,5,5,3,1,0]
temp2 = list(set(num2)) #先调用set()使用列表创建一个集合并返回一个集合,再调用list()将集合变成列表,但列表中的顺序不能保证相同,即会把列表中的元素排序
print(temp2)
访问集合中的值:
使用for循环一个一个读取集合中的数据:
例:>>> num2 = {1,2,3,4,5}
>>> num2
{1, 2, 3, 4, 5}
>>> for each in num2:
print(each)
输出结果:
1
2
3
4
5
使用in 和 not in判断元素是否存在集合中:
例:>>> num2 = {1,2,3,4,5}
>>> num2
{1, 2, 3, 4, 5}
>>> 1 in num2
True
>>> 6 in num2
False
>>> 1 not in num2
False
>>> 6 not in num2
add()方法:在集合中添加值
例:>>> num2
{1, 2, 3, 4, 5}
>>> num2.add(6)
>>> num2
{1, 2, 3, 4, 5, 6}
remove():将数值从集合中移除
例:>>> num2
{1, 2, 3, 4, 5, 6}
>>> num2.remove(6)
>>> num2
{1, 2, 3, 4, 5}
不可变集合:固定集合 一经创建即不可变
frozen关键字
例:>>> num3 = frozenset([1,2,3,4,5,6])
>>> num3
frozenset({1, 2, 3, 4, 5, 6})
>>> num3.add(8)
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
num3.add(8)
AttributeError: 'frozenset' object has no attribute 'add'
>>> num3.remove(6)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
num3.remove(6)
AttributeError: 'frozenset' object has no attribute 'remove'
21.文件:
open():成功打开文件后会返回一个文件对象
打开模式 执行操作
'r' 以只读的方式打开文件(默认)
'w' 以写入的方式打开文件,会覆盖已存在的文件,若无则创建
'x' 如果文件已经存在,使用此模式打开会引发异常
'a' 以写入模式打开,如果文件存在,则在末尾追加写入
'b' 以二进制模式打开文件
't' 以文本模式打开(默认)
'+' 可读写模式(可添加到其他模式中使用)
'U' 通用换行符支持
例:
>>> f = open('E:\\123.txt','r')
>>> f
<_io.TextIOWrapper name='E:\\123.txt' mode='r' encoding='cp936'>
文件对象方法:
f.close():关闭文件
f.read(size = -1):从文件中读取size个字符,当未给定size的值或者size值为负值时,读取剩余所有的字符,然后作为字符串返回
例:>>> f.read()
'尊敬的各位领导:\n你们好!\n首先无可非议的要郑重感谢河北科技师范学院校学生会给予我一个学期的工作机会。\n
由于个人的生涯规划和一些现实因素,经过慎重考虑之后,特此提出离职申请,敬请批准。\n
进入校会快半年了,在校会认识了许多人,也懂得了许多近似社会上的规则。在校会我学到了许多,
有过欢笑收获,也有过心酸和痛苦。在校会工作了近乎半年,给我的感觉是没有什么有意义的事,
我进行了反思,在极度不解的心情中我不知道我想干什么,爱好做什么也不清楚,一系列的问题让我很沮丧,
让我萌发了辞职的念头,经过深思熟虑,我却是了了这个念头,或许本本分分做一名学生才是我的下一步选择。\n
在这近乎半年的时间里,我有幸得到了各位部长和主席的倾心指导和热情的帮助,也谢谢各位部员们对我的帮助与理解,
衷心的祝愿河北科技师范学院校学生会发展得越来越好,各位主席,部长工作愉快,身体健康!\n此致\n
敬礼\n\n申请人:姚龙\n2017年2月18日\n'
>>> f.read()
''
f.close()
>>> f = open('E:\\123.txt','r')
>>> f.read(5)
'尊敬的各位'
f.readline():以写入模式打开,如果文件存在,则在末尾追加写入,读取一行
例:>>> f.seek(20,0)
20
>>> f.readline()
'们好!\n'
f.write(str):将字符串str写入到文件中 #打开文件模式必须有'w'或者'a'
例:>>> f = open('E:\\test.txt','w')
>>> f.write('helloworld')
10
f.close()
>>> f1 = open('E:\\test.txt')
>>> f1.read()
'helloworld'
f.writelines(seq):向文件写入字符串序列seq,seq应该是一个返回字符串的可迭代对象
f.seek(offset,from):在文件中移动指针,从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节
例:>>> f.seek(20,0)
20
>>> f.readline()
'们好!\n'
f.tell():返回当前在文件中的位置
例: >>> f = open('E:\\123.txt','r')
>>> f.read(5)
'尊敬的各位'
>>> f.tell()
10
读取文件:(高效)
例:>>> for each_line in f:
print(each_line)
输出结果:
尊敬的各位领导:
你们好!
首先无可非议的要郑重感谢河北科技师范学院校学生会给予我一个学期的工作机会。
由于个人的生涯规划和一些现实因素,经过慎重考虑之后,特此提出离职申请,敬请批准。
进入校会快半年了,在校会认识了许多人,也懂得了许多近似社会上的规则。在校会我学到了许多,有过欢笑收获,也有过心酸和痛苦。在校会工作了近乎半年,给我的感觉是没有什么有意义的事,我进行了反思,在极度不解的心情中我不知道我想干什么,爱好做什么也不清楚,一系列的问题让我很沮丧,让我萌发了辞职的念头,经过深思熟虑,我却是了了这个念头,或许本本分分做一名学生才是我的下一步选择。
在这近乎半年的时间里,我有幸得到了各位部长和主席的倾心指导和热情的帮助,也谢谢各位部员们对我的帮助与理解,衷心的祝愿河北科技师范学院校学生会发展得越来越好,各位主席,部长工作愉快,身体健康!
此致
敬礼
申请人:姚龙
2017年2月18日
文件操作实例:将456.txt文件中的数据进行分割,并按照以下要求保存:
1.A的对话单独保存为A_*.txt的文件(去掉A:)
2.B的对话单独保存为B_*.txt的文件(去掉B:)
3.文中共有三段对话分别保存为A_1.txt, B_1.txt, A_2.txt, B_2.txt, A_3.txt, B_3.txt,共6个文件(不同对话间已用===分割)
初始版本:
f = open('E:\\456.txt')
A = []
B = []
count = 1
for each_line in f:
#将对话进行分割,根据是否有5个=====进行分割成三段
if each_line[:5] != '=====':
#进行分割
(role, line_spoken) = each_line.split(':',1)
if role == 'A':
A.append(line_spoken)
if role == 'B':
B.append(line_spoken)
else:
#进行文件的保存
file_name_A = 'A_' + str(count) + '.txt'
file_name_B = 'B_' + str(count) + '.txt'
A_file = open(file_name_A,'w')
B_file = open(file_name_B,'w')
A_file.writelines(A)
B_file.writelines(B)
A_file.close()
B_file.close()
A = []
B = []
count += 1
#进行最后一段文件的保存,否则只保存两段
file_name_A = 'A_' + str(count) + '.txt'
file_name_B = 'B_' + str(count) + '.txt'
A_file = open(file_name_A,'w')
B_file = open(file_name_B,'w')
A_file.writelines(A)
B_file.writelines(B)
A_file.close()
B_file.close()
f.close()
优化版本:
def save_file(A,B,count):
#进行文件的保存
file_name_A = 'A_' + str(count) + '.txt'
file_name_B = 'B_' + str(count) + '.txt'
A_file = open(file_name_A,'w')
B_file = open(file_name_B,'w')
A_file.writelines(A)
B_file.writelines(B)
A_file.close()
B_file.close()
def split_file(filename):
f = open('E:\\456.txt')
A = []
B = []
count = 1
for each_line in f:
#将对话进行分割,根据是否有5个=====进行分割成三段
if each_line[:5] != '=====':
#进行分割
(role, line_spoken) = each_line.split(':',1)
if role == 'A':
A.append(line_spoken)
if role == 'B':
B.append(line_spoken)
else:
save_file(A,B,count)
A = []
B = []
count += 1
#进行最后一段文件的保存,否则只保存两段
save_file(A,B,count)
f.close()
split_file('456.txt')
22.模块:包含所有函数与变量的文件,类似于java中的导包,使用import关键字进行导包
os模块:
getcwd():返回当前工作目录
例:>>> import os
>>> os.getcwd()
'D:\\programer\\python'
chdir(path):改变工作目录
例:>>> os.chdir('E:\\')
>>> os.getcwd()
'E:\\'
listdir(path='.'):列举指定目录中的文件名('.'表示当前目录,'..'表示上一级目录)
例:>>> os.listdir()
['System Volume Information', '常用软件安装包', '达内', '复习资料', 'file', '学期末训练', '作业',
'pythonTest', 'JavaTest', '123.txt', 'test.txt', '456.txt']
mkdir(path):创建单层目录,如该目录已存在抛出异常
例:>>> os.mkdir('test')
>>> os.listdir()
['System Volume Information', '常用软件安装包', '达内', '复习资料', 'file', '学期末训练', '作业',
'pythonTest', 'JavaTest', '123.txt', 'test.txt', '456.txt', 'test']
>>> os.mkdir('E:\\达内')
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
os.mkdir('E:\\达内')
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'E:\\达内'
mkdirs(path):递归创建多层目录,如该目录已存在抛出异常,注意:'E:\\a\\b'和'E:\\a\\c'并不会冲突
例:>>> os.makedirs('E:\\test\\A')
>>> os.listdir('E:\\test')
['A']
remove():删除文件
例:>>> os.remove('E:\\test\\A\\test.txt')
>>> os.listdir('E:\\test\\A')
[]
rmdir():删除单层目录,如该目录非空则抛出异常
例:>>> os.rmdir('E:\\test\\A')
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
os.rmdir('E:\\test\\A')
OSError: [WinError 145] 目录不是空的。: 'E:\\test\\A'
>>> os.remove('E:\\test\\A\\test.txt')
>>> os.listdir('E:\\test\\A')
[]
>>> os.rmdir('E:\\test\\A')
>>> os.listdir('E:\\test')
[]
removedirs(path):递归删除目录,从子目录到父目录逐层尝试删除,遇到目录非空则抛出异常
例:>>> os.removedirs('E:\\test\\a\\b')
>>> os.listdir('E"\\test')
[]
rename(old,new):将文件old重命名为new
例:>>> os.rename('E:\\test','E:\\test123')
system(command):运行系统的shell命令
例:>>> os.system('cmd') #打开在当前工作区的cmd命令
>>> os.system('calc') #打开计算器
以下是支持路径操作中常用的一些定义,支持所有平台
os.curdir:指代当前目录('.')
例:>>> os.curdir
'.'
>>> os.listdir(os.curdir)
['System Volume Information', '常用软件安装包', '达内', '复习资料', 'file',
'学期末训练', '作业', 'pythonTest', 'JavaTest', '123.txt', 'test.txt', '456.txt', 'test123']
os.pardir:指代上一级目录('..')
例:>>> os.pardir
'..'
os.sep:输出操作系统特定的路径分隔符(Win下为'\\',Linux下为'/')
例:>>> os.sep
'\\'
os.lineseq:当前操作平台使用的行终止符(win下为'\r\n',Linux下为'\n')
例:>>> os.linesep
'\r\n'
os.name:指代当前使用的操作系统(包括:'posix','nt','mac','os2','ce','java')
例:>>> os.name
'nt'
os.path模块中关于路径常用的函数使用方法
basename(path):去掉目录路径,单独返回文件名
例:>>> os.path.basename('E:\\test\\a.txt')
'a.txt'
dirname(path):去掉文件名,单独返回目录路径
例:>>> os.path.dirname('E:\\test\\a.txt')
'E:\\test'
join(path1[,path2[,...]]):将path1,path2各部分组合成一个路径名
例:>>> os.path.join('A','B','C')
'A\\B\\C'
#如果要放在指定盘符里需自己加\\
>>> os.path.join('E:','A','B','C')
'E:A\\B\\C'
>>> os.path.join('E:\\','A','B','C')
'E:\\A\\B\\C'
split(path):分割文件名与路径,返回(f_path,f_name)元组。如果完全使用目录,它也会将最后一个目录作为文件名进行分离,
且不会判断文件或者目录是否存在
例:>>> os.path.split('E:\\a\\v\\c\\n')
('E:\\a\\v\\c', 'n')
>>> os.path.split('E:\\a\\v\\c\\a.txt')
('E:\\a\\v\\c', 'a.txt')
splittext(path):分离文件名与扩展名,返回(f_name,f_extension)元组
例:>>> os.path.splitext('a.txt')
('a', '.txt')
getsize(file):返回指定文件的尺寸,单位是字节
例:>>> os.path.getsize('E:\\123.txt')
791
getatime(file):返回指定文件最近访问时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)
例:>>> time.gmtime(os.path.getatime('E:\\test.txt'))
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=22, tm_hour=16, tm_min=0, tm_sec=0,
tm_wday=0, tm_yday=203, tm_isdst=0)
>>> time.localtime(os.path.getatime('E:\\test.txt'))
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=23, tm_hour=0, tm_min=0, tm_sec=0,
tm_wday=1, tm_yday=204, tm_isdst=0)
getctime(file):返回指定文件的创建时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)
getmtime(file):返回指定文件最新修改时间(浮点型秒数,可用time模块的gmtime()或localtime()函数换算)
exists(path):判断路径(目录或文件)是否存在(返回True或False)
例:>>> os.path.exists('E:\\123.txt')
True
isabs(path):判断指定路径是否为绝对路径
例:>>> os.path.isabs('E:\\123.txt')
True
>>> os.path.isabs('..\\123.txt')
False
23.pickle模块(主要用于复杂字典产生的文件的输入输出):二进制转换字节流:pickling 二进制转换为对象:unpickling
例:>>> import pickle
>>> my_list = [1,2,12.2,'nihao',['hello world']]
>>> pickle_file = open('my_list.abv','wb') #会产生一个my_list.adv的文件
>>> pickle.dump(my_list,pickle_file)
>>> pickle_file.close()
>>> pickle_file = open('my_list.abv','rb')
>>> my_list2 = pickle.load(pickle_file)
>>> print(my_list2)
[1, 2, 12.2, 'nihao', ['hello world']]
24.exception(常见Exception)
AsserttonError:断言异常
IndexError:索引超出范围
OSError:操作系统产生的异常
TypeError:不同类型间的无效操作
SyntaxError:Python的语法错误
ZeroDivisionError:除数为零
NameError:尝试访问一个不存在的变量
exception处理:(一个try可跟多个except使用)
try:
检测范围
except Exception[as reason]
出现异常(Exception)后的处理代码
finally:
无论如何最终都会进行该段代码
例:f = open('我是个文件.txt','wb')
print(f.read())
f.close()
E:\pythonTest\venv\Scripts\python.exe E:/pythonTest/venv/Include/ScoreTest.py
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 173, in <module>
print(f.read())
io.UnsupportedOperation: read
try:
f = open('我是个文件.txt')
print(f.read())
f.close()
except OSError as reason:
print('文件出错!\n出错原因:' + str(reason))
>>>
==================== RESTART: C:/Users/全球/Desktop/test.py ====================
文件出错!
出错原因:[Errno 2] No such file or directory: '我是个文件.txt'
自行引发异常:raise Error('某error')
25.else语句:
(1):与if搭配:要么怎样,要么不怎样
例:if a > b:
print(a)
else:
print(b)
(2):与for/while搭配,干完了能怎样,干不完就别想怎样
例:#找出最大约数
def showMaxFactor(num):
count = num // 2
while count > 1:
if num % count == 0:
print('%d的最大约数是%d' % (num,count))
break
count -= 1
else:
print('%d是素数' % num)
num = int(input('请输入一个数'))
showMaxFactor(num)
(3):与异常处理进行搭配,没有问题那就干吧
例:try:
int('abc')
except ValueError as reason:
print('出错!' + str(reason))
else:
print('无异常!')
E:\pythonTest\venv\Scripts\python.exe E:/pythonTest/venv/Include/ScoreTest.py
出错!invalid literal for int() with base 10: 'abc'
try:
int('123')
except ValueError as reason:
print('出错!' + str(reason))
else:
print('无异常!')
E:\pythonTest\venv\Scripts\python.exe E:/pythonTest/venv/Include/ScoreTest.py
无异常!
26.with语句:
例:
未使用with:
try:
f = open('snv.txt','w')
for each_line in f:
print(each_line)
except OSError as reason:
print('出错!' + str(reason))
finally:
f.close()
#没有该文件所以报错!
E:\pythonTest\venv\Scripts\python.exe E:/pythonTest/venv/Include/ScoreTest.py
出错!not readable
使用with:在文件不使用时python会自行关闭文件
try:
with open('snv.txt','w') as f:
for each_line in f:-
print(each_line)
except OSError as reason:
print('出错!' + str(reason))
E:\pythonTest\venv\Scripts\python.exe E:/pythonTest/venv/Include/ScoreTest.py
出错!not readable
26.Python中的 // 与 / 的区别
" / " 表示浮点数除法,返回浮点结果;
" // " 表示整数除法,返回不大于结果的一个最大的整数
【code】
print("6 // 4 = " + str(6 // 4))
print("6 / 4 =" + str(6 / 4))
【result】
6 // 4 = 1
6 / 4 =1.5
27.EasyGUI(自行查找官方api使用)
导包的三种方式:
例1:import easygui
easygui.msgbox('hello')
例2:from easygui import *
msgbox('hello')
例3:import easygui as g
g.msgbox('hello')
建议:不在IDLE上运行EasyGUI
28.类和对象(与java类似,但python类没有权限控制)
对象 = 属性 + 方法
例:class Test:
height = 175
name = '李四'
age = 18
def eat(self): #self相当于C++的this指针
print('在吃饭')
test = Test()
test.eat()
输出结果:在吃饭
OO的特征:
1.封装:信息隐蔽技术
2.继承:子类自动共享父类之间的数据和方法的机制
3.多态:不同对象对同一方法响应不同的行动
self是什么:(主要用于辨别哪个对象调用,如a.setName()就会将a这个对象传进去)
class Ball:
def setName(self, name):
self.name = name
def kick(self):
print('我叫%s,有人在踢我' %self.name)
a = Ball()
a.setName('球A')
b = Ball()
b.setName('球B')
c = Ball()
c.setName('土豆')
a.kick()
c.kick()
__init__(self): (类似构造函数)
例:class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print('我叫%s,有人在踢我' %self.name)
b = Ball('篮球')
b.kick()
输出结果:我叫篮球,有人在踢我
c = Ball()
c.kick()
输出结果:Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 285, in <module>
c = Ball()
TypeError: __init__() missing 1 required positional argument: 'name'
公有和私有:
在python中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数或变量就变成了私有的了
公有例1:
class Person:
name = '小弘'
p = Person()
print(p.name)
输出结果:小弘
私有例2:
class Person:
__name = '小弘'
p = Person()
print(p.__name)
输出结果:Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 298, in <module>
print(p.__name)
AttributeError: 'Person' object has no attribute '__name'
print(p.name)
输出结果:
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 299, in <module>
print(p.name)
AttributeError: 'Person' object has no attribute 'name'
访问私有变量:
例:
class Person:
__name = '小弘'
def getName(self):
return self.__name
p = Person()
#print(p.name)
print(p.getName())
输出结果:小弘
私有变量python自动改名为:_类名__变量名
例:
class Person:
__name = '小弘'
def getName(self):
return self.__name
p = Person()
#print(p.name)
#print(p.getName())
print(p._Person__name)
输出结果:小弘
29.继承:
语法:class DrivedClassName(BaseClassName父类/基类/超类):
例:
class Parent:
def hello(self):
print('正在调用父类的方法...')
class Child(Parent):
#Python pass 是空语句,是为了保持程序结构的完整性。
#pass 不做任何事情,一般用做占位语句。目的是防止报错
pass
p = Parent()
print(p.hello())
输出结果:正在调用父类的方法...
None
c = Child()
print(c.hello())
输出结果:正在调用父类的方法...
None
注意:如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性(类似java的重写)
例:
class Parent:
def hello(self):
print('正在调用父类的方法...')
class Child(Parent):
def hello(self):
print('正在调用子类的方法')
p = Parent()
print(p.hello())
c = Child()
print(c.hello())
输出结果:
正在调用父类的方法...
None
正在调用子类的方法
None
继承的两种方法:1.调用未绑定的父类方法
2.使用super函数
例1:父类.父类函数/属性名
例2:super().需要的函数的方法#不用给定任何父类的名字,python内部机制自动寻找
多重继承:(当不能确定是否必须使用多重继承时尽量不用,会出现不可预知的bug)
语法:class DrivedClassName(Base1, Base2, Base3):
例:
class Base1:
def fool1(self):
print('我是Base1的fool1')
class Base2:
def fool2(self):
print('我是Base2的fool2')
class C(Base1,Base2):
pass
c = C()
print(c.fool1())
print(c.fool2())
输出结果:
我是Base1的fool1
None
我是Base2的fool2
None
30.组合(把类的实例化放到一个新类里边,利用__init__(self)函数进行构造方法实例化,主要用于无继承关系但互相有关联的类)
例:
class Turtle:
def __init__(self, x):
self.num = x
class Fish:
def __init__(self, x):
self.num = x
class Pool:
def __init__(self, x, y):
self.turtle = Turtle(x)
self.fish = Fish(y)
def print_num(self):
print('水池中有乌龟 %d 只,小鱼 %d 只' %(self.turtle.num, self.fish.num))
pool = Pool(1,2)
pool.print_num()
输出结果:水池中有乌龟 1 只,小鱼 2 只
31.类、类对象、实例对象
例:
class C:
count = 0
a = C()
b = C()
c = C()
print(a.count)
print(b.count)
print(c.count)
c.count += 10 #对c的属性进行赋值
print(a.count)
print(b.count)
print(c.count)
print(C.count)
C.count += 100
print(a.count)
print(b.count)
print(c.count)
输出结果:
0
0
0
0
0
10
0
100
100
10
说明:类定义C ---> 类对象C ---> 实例对象a、b、c
类定义与类对象相互绑定,类似于static 对实例对象c的加减并不会影响类定义C和类对象C,改变的只是实例对象c的自身,
实例属性c.count将类对象覆盖
属性的名字和方法的名字相同时,属性会覆盖方法
例:
class C:
def x(self):
print('X')
c = C()
print(c.x())
输出结果:X
c.x = 1
print(c.x)
输出结果:1
print(c.x())
输出结果:
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 401, in <module>
print(c.x())
TypeError: 'int' object is not callable
类定义命名规则:
1.不要在一个类中定义所有能想到的属性和方法,应该用继承和组合机制来进行扩展
2.用不同的词性进行命名,如属性名用名词,方法名用动词
什么是绑定:(self的绑定作用)
python严格要求方法需要有实例才能被调用,这种限制就是python所谓的绑定概念
类中定义的属性和方法都是静态的,及时类删除也能调用
32.继承相关的BIF:
(1).issubclass(class, classinfo):一个类被认为是其自身的子类,其中classinfo可以是类对象组成的元组,
只要class是其中任何一个候选类的子类,则返回True
例:
class A:
pass
class B(A):
pass
print(issubclass(B,A))
print(issubclass(B, B))
print(issubclass(B, object)) #object类是所有类的父类
输出结果: True
True
True
(2).isinstance(object, classinfo):检查一个对象是否是一个类的实例对象,其中classinfo可以是类对象组成的元组,
只要object是其中任何一个候选类的实例对象,则返回True
例:
class A:
pass
class B(A):
pass
class C:
pass
b1 = B()
print(isinstance(b1,B))
print(isinstance(b1,A))
print(isinstance(b1, (A, B, C)))
输出结果:True
True
True
(3).hasattr(object, name): attr = attribute:属性 用于测试一个对象里面是否含有指定的属性
例:
class C:
def __init__(self, x=0):
self.x = x
c1 = C()
print(hasattr(c1,'x'))
输出结果:True
#属性名是字符串,不是变量
print(hasattr(c1,x))
输出结果:
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 441, in <module>
print(hasattr(c1,x))
NameError: name 'x' is not defined
(4).getattr(object, name[,default]):返回对象指定的属性值,如果指定的属性值不存在,则返回设定的default值
例:
class C:
def __init__(self, x=0):
self.x = x
c1 = C()
print(getattr(c1, 'x'))
输出结果:0
print(getattr(c1, x))
输出结果:
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 444, in <module>
print(getattr(c1, x))
NameError: name 'x' is not defined
print(getattr(c1, 'y', '所访问的属性不存在。。。'))
输出结果:所访问的属性不存在。。。
(5).setattr(object, name, value):设定对象中指定的属性值,如果属性不存在,则新建这个属性并赋值
例:
class C:
def __init__(self, x=0):
self.x = x
c1 = C()
setattr(c1, 'y', '您所访问的属性现在存在了')
print(getattr(c1, 'y'))
输出结果;您所访问的属性现在存在了
(6).delattr(object, name):删除对象中指定的属性,如果属性不存在,则抛出异常
例;
class C:
def __init__(self, x=0):
self.x = x
c1 = C()
setattr(c1, 'y', '您所访问的属性现在存在了')
delattr(c1, 'y')
print(getattr(c1, 'y', 'y现在已经被删除'))
输出结果:y现在已经被删除
#使用delattr(object, name)之前要用hasattr(object, name)检测该属性是否存在
delattr(c1, 'y')
输出结果:
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 454, in <module>
delattr(c1, 'y')
AttributeError: y
(7).property(fget=None#获取属性的方法, fset=None#设置属性的方法, fdel=None#删除属性的方法, doc=None):
通过属性来设置属性;优势或用处:便于维护代码,不必更改大量代码
例:
class C:
def __init__(self, size=10):
self.size = size
def getSize(self):
return self.size
def setSize(self, sizeValue):
self.size = sizeValue
def delSize(self):
del self.size
x = property(getSize, setSize, delSize)
c1 = C()
#原方法获得size值:
print(c1.getSize())
输出结果:10
#使用property获取size的值
print(c1.x)
输出结果:10
#使用property设置size的值
c1.x = 20
print(c1.x)
输出结果:20
print(c1.size)
输出结果:20
print(c1.getSize())
输出结果:20
#使用property删除size的值
del c1.x
print(c1.size)
输出结果:
Traceback (most recent call last):
File "E:/pythonTest/venv/Include/ScoreTest.py", line 482, in <module>
print(c1.size)
AttributeError: 'C' object has no attribute 'size'
33.魔法方法:总是被双下划包围,如:__init__
(1).__init__(self[,...]):类似java的构造方法:
例1:
class Rectabgle:
def __init__(self, x, y):
self.x = x
self.y = y
def getPeri(self):
return (self.x + self.y)*2
def getArea(self):
return self.x * self.y
rect = Rectabgle(3,4)
print(rect.getPeri())
输出结果:14
print(rect.getArea())
输出结果:12
例2:
#__init__(self)方法无返回值
>>>class A:
def __init__(self):
return 'A for A_class'
>>> a = A()
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
a = A()
TypeError: __init__() should return None, not 'str'
(2).__new__(cls[, ...]):实例化方法时调用的第一个方法,返回cls类的实例化对象,一般不需要重写这个方法,当继承一个不可变类但又需要对其修改时需要重写
例:
#将字符串全部改为大写
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return str.__new__(cls, string)
world = CapStr('Hello World!')
print(world)
输出结果:HELLO WORLD!
(3).__del__(self):垃圾回收机制,当所有对象的引用都被清理之后才会启动这个垃圾回收机制
例:
>>> class C:
def __init__(self):
print('__init__方法')
def __del__(delf):
print('__del__方法')
>>> c1 = C()
__init__方法
>>> c2 = c1
>>> c3 = c2
>>> del c3
>>> del c2
>>> del c1
__del__方法
(3).工厂函数(类对象)
__add__(self,other):定义加法的行为:+
__sub__(self,other):定义减法的行为:-
注意:易出现无线递归
例:
class New_int(int):
def __add__(self, other):
return int.__sub__(self, other)
def __sub__(self, other):
return int.__add__(self, other)
a = New_int(3)
b = New_int(5)
print(a + b)
print(a - b)
输出结果: -2
8
错误示范:(出现无限递归直至内存溢出)
class Try_int(int)
def __add__(self, other):
return self + other
def __sub__(self, other):
return self - other
a = Try_int(3)
b = Try_int(5)
print(a+b)
输出结果:出现无限递归直至内存溢出
更改:
class Try_int(int):
def __add__(self, other):
return int(self) + int(other)
def __sub__(self, other):
return int(self) - int(other)
a = Try_int(3)
b = Try_int(5)
print(a + b)
输出结果:8
__mul__(self,other):定义乘法的行为:*
__truediv__(self,other):定义真除法的行为:/
__floordiv__(self,other):定义整数除法的行为://
__mod__(self,other):定义取模除法的行为:%
__divmod__(self,other):定义当被divmod()调用时的行为,divmod(a,b)返回值是一个元组:(a//b, a%b)
__pow__(self,other[,modulo]):定义当被power()调用或**运算时的行为
__lshift__(self,other):定义按位左移的行为:<<
__rshift__(self,other):定义按位右移的行为:>>
__and__(self,other):定义按位与操作的行为:&
__xor__(self,other):定义按位异或操作的行为:^
__or__(self,other):定义按位或操作的行为:|
__str__(self):定义字符串的行为:
例:
class A():
def __str__(self):
return 'hello world!'
a = A();
print(a)
输出结果:hello world!
__repr__(self):定义字符串的行为:
例:
class B():
def __repr__(self):
return 'hello world!'
b = B()
print(b)
输出结果:hello world!
34.魔法方法的定制类(计时器)的练习
#类的定制
#定制一个计时器的类,start和stop方法代表启动计时和终止计时。假设计时器对象t1,print(t1)
#和直接调用t1均显示结果;当计时器未启动或已经停止计时,调用stop方法会给予温馨提示。
#两个计时器对象可以进行相加:t1+t2,只能使用提供的有限资源完成
#资源:使用time模块的localtime方法获取时间。
#time.localtime返回struct_time的时间格式
#表现你的类:__str__和__repr__
import time as t
class MyTimer():
def __init__(self):
self.unit = ['年', '月', '日', '时', '分', '秒']
self.prompt = '未开始计时'
self.lasted = []
self.begin = 0
self.end = 0
def __str__(self):
return self.prompt
__repr__ = __str__
def __add__(self, other):
prompt = '总共运行了'
result = []
for index in range(6):
result.append(self.lasted[index] + other.lasted[index])
if result[index]:
prompt += (str(result[index]) + self.unit[index])
return prompt
# 开始计时:
def start(self):
self.begin = t.localtime()
self.prompt = '提示:请先调用stop()停止计时'
print('开始计时!')
# 计时结束:
def stop(self):
if not self.begin:
print('请先调用start()开始计时')
else:
self.end = t.localtime()
self._calc()
print('计时结束!')
# 计算时长:
def _calc(self):
self.lasted = []
self.prompt = '总共运行了'
for index in range(6):
self.lasted.append(self.end[index] - self.begin[index])
if self.lasted[index]:
self.prompt += (str(self.lasted[index]) + self.unit[index])
# 为下一轮计时进行初始化:
self.begin = 0
self.end = 0
测试结果:
================== RESTART: C:/Users/全球/Desktop/MyTimer.py ==================
>>> t1 = MyTimer()
>>> t2 = MyTimer()
>>> t1.start()
开始计时!
>>> t1.stop()
计时结束!
>>> t2.start()
开始计时!
>>> t2.stop()
计时结束!
>>> t1 + t2
'总共运行了12秒'
>>> t1
总共运行了6秒
>>> t2
总共运行了6秒
>>> t1 = MyTimer()
>>> t2 = MyTimer()
>>> t1.start()
开始计时!
>>> t2.start()
开始计时!
>>> t1.stop()
计时结束!
>>> t2.stop()
计时结束!
>>> t1
总共运行了9秒
>>> t2
总共运行了9秒
>>> t1+t2
'总共运行了18秒'
>>> t1.stop()
请先调用start()开始计时
注:
如果开始的时间是(2022年2月22日16:30:30),停止时间是(2025年1月23日15:30:30),那
按照停止时间减去开始时间的计算方式就会出现负数(3年-1月1天-1小时),因此要做一些转换
35.序列相加:
例:
list1 = [1,2,3,'hello',4]
list2 = [5,6,7,'world',9,10]
print(list1 + list2)
#输出结果:[1, 2, 3, 'hello', 4, 5, 6, 7, 'world', 9, 10]