人生苦短,Python當歌! 此篇博客是本人学习python过程中,总结的基础知识点,希望可以帮到有需要的朋友,如有不足或错误之处,希望评论指出,感谢大家!!
第一章 计算机基础
1.1 硬件
计算机的硬件由:CPU /内存 /主板 /硬盘 /显卡等组成
内存:
优点:存取速度快
缺点:断电后数据全部丢失
硬盘:
优点:断电后数据也会永久保存
缺点:存取速度远远慢于内存
1.2 操作系统:
操作系统用于协同或控制硬件之间进行工作
- windows : win7 / win10/ xp ...
- linux(开源,免费):
- centos(公司主要用的)
- ubuntu:适合个人开发,图形化界面好
- redhat:企业级
- Mac 适合办公
1.3 解释器和编译器
编程语言的开发者写的一个工具,将用户写的代码转换成二进制交给操作系统去执行
1,4 解释型语言和编译型语言
- 解释型:写完代码后,交给计算机一行一行执行,边解释边执行 如:python / PHP/Ruby...
- 编译型:写完代码后,编译器将其变成另一个文件,再交给计算机去执行 如 :c / c++ / java...
1.5 进制
对于计算机而言,无论文件储存 / 网络传输等本质上都是二进制.微信/QQ等发的信息,图片,视频都是二进制
进制:
-
2进制: 计算机内部
-
8进制
-
10进制:人使用计算机一般都是10进制,计算机内部会将其转换成二进制
-
16进制:一般用于表示(用更短的内容表示更多的东西.一般是: x 开头
第二章 python 入门
2.1 编程是什么
- 什么是编程语言
- 语言是一个事物与另一个事物沟通的介质
- 编程语言就是程序员与计算机沟通的介质
- 什么是编程
- 编程就是程序按照某种编程语言的语法规范将自己想要让计算机做的事表达出来
- 表达的结果就是程序,程序就是一系列的文件
- 为什么要编程
- 在编程的过程中,计算机就像是人的奴隶
- 我们编程的目的就是让计算机代替人类去工作,从而解放人力
2.2 环境的安装
- 安装解释器:py2 / py3 (注意环境变量问题)
- 安装开发工具:pycharm
2.3 编码
-
ASCII :8位表示一个东西,只能识别英文
-
Unicode(万国码): 一个中文或字母等于四个字节,最多32位表示,内存进行数据计算时使用
-
utf-8:给万国码压缩,一个中文等于3个字节,一个英文一个字节,一般网络传输和文件存储时使用此编码
-
gbk : 一个中文两个字节
-
gb2312
注意:文件以什么方式保存就要以什么方式打开
2.4 解释器编码相关
-
py2默认解释器编码:ASCII
-
py3默认解释器编码:utf-8
如想修改默认编码,则可以使用:
# -*- coding:utf-8 -*-
2.5 变量
为什么要有变量?
为某个值创建一个“外号”,以后在使用时候通过此外号就可以直接调用。
- 变量的要求:
- 只能包含数字 / 字母 / 下划线
- 不能是数字开头
- 不能包含python中的关键字
- 建议
- 见名知意
- 用下划线连接
2.6 输出 输入
-
输出:
py2: print '你好' py3: print('你好')
-
输入 : 得到的内容永远是字符串
py2 raw_input("xxx") py3 input('xxx')
#示例 user_name = input("请输入你的姓名:") password = input("请输入你的密码:") content = "你的用户名是:" + user_name + "; 你的密码是:" + password print(content)
2.7 注释
# 单行注释
'''
多行注释
'''
2.8 if 条件语句
# :示例:让用户输入一个数字,猜:如果数字 > 50,则输出:大了; 如果数字 <= 50 ,则输出:小了。
num = input('请输入一个数字')
number = int(num)
if number > 50:
print('大了')
else:
print('小了')
2.9 循环
-
while 循环
while 条件表达式: 循环体 # 当条件表达式的返回值为真时,则执行循环体中的语句,执行完毕后,重新判断条件表达式的返回值,直到表达式的返回的结果为假时,退出循环.
-
for 循环
for 某个变量 in 要循环的对象: 循环体 # 其中某个变量是用于保存读取出的值,对象为要遍历或迭代的对象,可以是任何有序的序列对象,如字符串.列表.元组等.循环体为一组被重复执行的语句
死循环考虑while, 有限循环优先考虑for循环
-
break 语句
意思为结束当前循环
-
continue 语句
意思:当循环遇到continue时,不再继续往下走,而是回到当前循环
2.30 字符串格式化
-
%s: (字符串占位符)
name = input('姓名:') do = input('在干什么:') template = "%s在教室,%s。" %(name,do,) print(template)
-
%d (数字占位符)
template = "我是%s,年龄%d, 职业%s。" %("alex",73,'讲鸡汤',) print(template)
-
%%
name = 'alex' template = "%s现在手机的电量是100%%" %(name,) print(template)
2.31 运算符
-
算数运算
示例: 1 ~ 100 之间所有的数相加。 total = 0 count = 1 while count <=100: total += count count += 1 print(total)
-
赋值运算
-
逻辑运算
-
or
对于 or,如果有遇到 value= 1 or 9 第一个值如果是转换成布尔值如果是真,则value=第一值。 第一个值如果是转换成布尔值如果是假,则value=第二值。 如果有多个or条件,则从左到右依次进行上述流程
-
and
对于and,如果遇到 value= 1 and 9 如果第一个值转换成布尔值是True,则value=第二个值 如果第一个值转换成布尔值是False,则value=第一个值。 如果有多个and条件,则从左到右依次进行上述流程
-
优先级
在没有()的情况下not 优先级高于 and,and优先级高于or,即为( )>数学运算>not>and>or,同一优先级从左往右计算
示例: not 2 > 1 and 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 False 3 > 1 and 2 or 2 < 3 and 3 and 4 or 3 > 2 2
-
第三章 数据类型
3.1 None
表示空(无任何功能,专门用于提供空值)
3.2 整形(int)
-
py2:整型除法只能保留整数位。
from __future__ import division v = 9 /2 print(v) #保留全部值
-
py3
- 只有int
- 整型除法保留所有。
3.3 布尔类型(bool)
只有两个结果:True/False:
0/''/[]/()/{}/set() 转布尔时为False,其余结果都为Ture
3.4 字符串(str) :
- 不可变类型,不可删除或修改
-
upper:转大写 lower:转小写
name = 'alex' new_name = name.upper() print(new_name) # ALEX
-
isdigit:判断是否是数字,但常用 isdecimal 来判断
v = '1' # v = '二' # v = '②' v1 = v.isdigit() # '1'-> True; '二'-> False; '②' --> True v2 = v.isdecimal() # '1'-> True; '二'-> False; '②' --> False v3 = v.isnumeric() # '1'-> True; '二'-> True; '②' --> True print(v1,v2,v3) # 以后推荐用 isdecimal 判断是否是 10进制的数。
-
strip: 去除空白,也可以去除换行符( )和指定字符串
v1 = "alex " print(v1.strip()) v1 = "alexa" print(v1.strip('al'))
-
replace:替换
content = '去你大爷的' con = content.replace('大爷','**') #当替换的内容有多个时,后面可以加入数字,代表替换前几个内容 print(con) # 去你**的
-
split:切割 ,得到的是一个列表
content = '12|22,33|44' con = content.split('|') print(con) #['12', '22,33', '44']
-
format:字符串格式化
name = '我是{0},今年{1}'.format('Alex',20,) print(name)
-
startswith:判断以什么开头 endswith:判断以什么结尾 结果为Ture/False
name = 'alex' flag = name.startswith('al') print(flag) # Ture
-
encode:转换编码
name = '张三' # 解释器读取到内存后,按照unicode编码存储:8个字节。 v1 = name.encode('utf-8') print(v1) # 转换成了6个字节
-
join: 循环某个元素,并以某个东西连接起来
name = 'Alex' new_name = '-'.join(name) #注意:join连接的必须的字符串,如果不是需要先转化为字符串再进行连接 print(new-name) # A-l-e-x
-
isalnum() 判断字符串是否由字母或数字组成
-
isalpha() 判断字符串只有字母组成
3.5 列表(list) :
- 可变类型,需要新的变量去接收
-
append:在列表末追加元素
v = [1,2,3,4,5] v.append(6) print(v) #[1,2,3,4,5,6]
-
insert:在列表指定索引值前面加入元素
v= [1,2,3,4] v.insert(0,6) print(v) #[6,1,2,3,4]
-
extend: 逐个加入
v = [1,2,3] name = 'Alex' v.extend(name) #加入的可以是字符串/元组/列表/集合 print(v) #[1,2,3,A,l,e,x]
-
remove:删除指定元素
v = [123,23,45] v.remove(23) print(v) #[123,45]
-
pop: 根据索引位置进行删除
v = [123,23,45] a = v.pop(0) #pop()默认删除最后一个元素,会将删除的那个元素返回回去 print(v,a) # 123 [23,45]
-
del ;删除
v = [123,23,45] del v[0] print(v) #[23,45]
-
修改
v = [123,23,45] v[0] = 11 print(v) #[11,23,45]
-
reverse :反转
v = [123,23,45] v.reverse() print(v) #[45,23,123]
-
sort: 排序
v= [2,6,4,8,1] v.sort(reverse=True) #从大到小排列 v.sort(reverse=False) #从小到大排列 v.sort() #默认是从小到大排列 print(v)
-
枚举和索引
lis = [11,22,33,44] for index ,item in enumerate(lis,1) print(index,item) print(lis.index(33)) # 2
3.6 字典(dict) : 无序
-
格式
data = {键:值,键:值,键:值,键:值,键:值,键:值,} #键值对 嵌套中: # 值可以用任何东西表示 # 键不能用列表/字典/集合(等可变类型)表示,其他都可以
-
keys 取所有的键
data = {11:22,33:44,55:66} for k in data.keys(): print(k) #11,33,55
-
values 取所有的值
data = {11:22,33:44,55:66} for v in data.values(): print(v) # 22,44,66
-
items 取所有的键值对
data = {11:22,33:44,55:66} for k,v in data.items(): print(k,v) 注意: a,b,c = [1,2,3] print(a,b,c) #a=1,b=2,c=3
-
get取值
info = {'k1':'v1','k2':'v2'} v1 = info['k1'] # v1 v2 = info.get('k1') # v1 (常用此方法) v3 = info.get('k111',666) # 666 (不在字典范围内则打印后面的内容) v4 = info.get('k111') # None
-
修改 (存在就修改/不存在就增加)
data = {11:22,33:44,55:66} data[11] = 99 print(data) # {11: 99, 33: 44, 55: 66} data[77] = 88 print(data) # {11: 22, 33: 44, 55: 66, 77: 88}
-
删除 (del)
data = {11:22,33:44,55:66} del data[11] # 删除了一个键值对 print(data) # {33:44,55:66}
-
pop 删除
info = {'k1':'v1','k2':'v2'} result = info.pop('k2') #v2 print(info,result) #{'k1':'v1'} v2
-
update 批量添加
info = {'k1':'v1','k2':'v2'} #不存在就添加,存在就覆盖 info.update({'k3':'v3','k4':'v4','k2':666}) print(info) # {'k1': 'v1', 'k2': 666, 'k3': 'v3', 'k4': 'v4'}
3.7 集合(set) ;
- 无序 / 无重复 空集合: set()
-
交集 (intersection)
a = {1,2,3,4,5,} b = {2,4,6,7} c = a.intersection(b) print(c) # {2, 4}
-
并集(union)
a = {1,2,3,4,5,} b = {2,4,6,7} c = a.union(b) print(c) # {1, 2, 3, 4, 5, 6, 7}
-
差集(difference)
a = {1,2,3,4,5} b = {2,4,6,7} c = a.difference(b) #{1,3,5} c = b.difference(a) #{6,7}
-
单个添加 ;add
a = {1,2,3,4,5} a.add(67) #只能添加单个元素 print(a) #{1, 2, 3, 4, 5, 67}
-
批量添加: update
v = {1,2,3,4,} v.update({5,6,7}) #后面的只能是集合/字典/元组/列表,不能是单独的几个元素 print(v) #{1,2,3,4,5,6,7}
-
删除: discard
v = {1,2,45} v.discard(45) #删除指定元素 print(v) #{1,2}
-
注意
#嵌套时 列表/字典/集合 不能作为集合里面的元素
3.8 公共功能
-
len(计算长度) 都可以
-
索引 集合是无序的所以没有,其余都有
-
切片 字典和集合没有,其余都有
-
步长 字典和集合没有,其余都有 " 通过步长可以反转字符串:[ : : -1 ]"
-
for 循环 都可以
-
删除 字符串 / 元组 是不可变类型,所以不能删除,其余都有
-
修改 字符串 / 元组 是不可变类型,所以不能删除,其余都有
第四章 文件操作
4.1 读 / 写 操作
-
读取: r (read):只能读不能写,文件不存在就报错
#打开文件: object = open('某个文件',mode = 'r',encoding = '编码') #读取文件所有内容到内存: content = object.read() print(content) #读取文件的所有内容到内存,并按照每一行进行分割到列表中。 content = object.readlines() print(content) # 读取文件的第一行: content= object.readline() 此时光标在第一行的末端 #如果以后读取一个特别大的文件 for line in object: #一行一行进行读取 line = object.strip() #去除换行最后一个换行 print(line) #关闭内容: object.close()
-
read(): 全部读到内存
-
read(1)
-
1表示一个字符
obj = open('某个txt文件',mode='r',encoding='utf-8') data = obj.read(1) # 1个字符 obj.close() print(data)
-
1表示一个字节(二进制中)
obj = open('某个txt文件',mode='rb') # b:二进制的意思 data = obj.read(1) # 1个字节 obj.close()
-
-
-
写入:w (write): 只能写不能读(先清空文件),文件不存在就新建
#打开文件: object = open('某个文件或要新建的文件',mode = 'w',encoding = '编码') #写内容: object.write('xxx') #关闭文件: object.close()
-
write(字符串)
obj = open('某个txt文件或要新建的文件',mode='w',encoding='utf-8') obj.write('你好') obj.close()
-
write(二进制)
obj = open('某个文件或要新建的文件',mode='wb') # obj.write('你好'.encode('utf-8')) v = '你好'.encode('utf-8') obj.write(v) obj.close()
-
-
追加; a (append): 只能追加不能读,不存在则新建
#打开文件: object = open ('某个txt文件或要新建的文件',mode = 'a',encoding = '编码') #写内容: object.append() #关闭文件 object.close()
4.2可读可写:
- r+
- 读:默认从0的光标开始读,也可以通过 seek 调整光标的为位置。
- 写:从光标所在的位置开始写,也可以通过 seek 调整光标的位置。
- w+
- 读:默认光标永远在写入的最后或0,也可以通过 seek 调整光标的位置。
- 写:先清空。
- a+
- 读:默认光标在最后,也可以通过 seek 调整光标的位置。然后再去读取。
- 写:永远写到最后。
4,3 其他操作:seek / tell / flush
-
seek(光标字节位置),无论模式是否带b,都是按照字节进行处理。
obj = open('某个txt文件',mode='r',encoding='utf-8') obj.seek(3) # 跳转到指定字节位置,读取后面内容 data = obj.read() obj.close() print(data) obj = open('a.txt',mode='rb') obj.seek(3) # 跳转到指定字节位置 data = obj.read() obj.close() print(data)
-
tell(), 获取光标当前所在的字节位置
obj = open('a.txt',mode='rb') obj.read() data = obj.tell() print(data) obj.close()
-
flush,强制将内存中的数据写入到硬盘
v = open('a.txt',mode='a',encoding='utf-8') while True: val = input('请输入:') v.write(val) v.flush() v.close()
4.4 关闭文件
v = open('a.txt',mode='a',encoding='utf-8')
v.close()
with open('a.txt',mode='a',encoding='utf-8') as v:
data = v.read()
# 缩进中的代码执行完毕后,自动关闭文件
4.5 文件内容的修改
with open('a.txt',mode='r',encoding='utf-8') as f1:
data = f1.read()
new_data = data.replace('飞洒','666')
with open('a.txt',mode='w',encoding='utf-8') as f1:
data = f1.write(new_data)
-
大文件修改
f1 = open('a.txt',mode='r',encoding='utf-8') f2 = open('b.txt',mode='w',encoding='utf-8') #先打开两个文件,再进行操作 for line in f1: # 一行一行进行修改 new_line = line.replace('要被修改的内容','被修改后的内容') f2.write(new_line) f1.close() f2.close() #另一种写法: with open('a.txt',mode='r',encoding='utf-8') as f1, open('c.txt',mode='w',encoding='utf-8') as f2: for line in f1: new_line = line.replace('要被修改的内容','被修改后的内容') f2.write(new_line)
第五章 函数
5.0 三元计算(三目计算)
v = 前面 if 条件 else 后面
if 条件:
v = '前面'
else:
v = '后面'
5.1 函数基本认识
-
目前:面向过程编程 [可读性差/可重复性差]
-
函数式编程
- 本质:将N行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码并执行
- 场景
- 代码重复执行
- 代码量特别多超过一屏,可以选择通过函数进行代码的分割
-
函数的基本结构
#函数的定义 def 函数名(参数): #函数内容 #函数的执行 函数名(参数)
示例: def get_list_first_data(): v = [11,22,33,44] print(v[0]) get_list_first_data() #注意:函数如果不被调用,则内部代码永远不会执行
-
参数
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。 这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
示例:打印某个列表的元素 def get_list_first_data(aaa): # aaa叫形式参数(形参) v = [11,22,33,44] print(v[aaa]) get_list_first_data(1) # 调用函数时传递叫:实际参数(实参)
-
返回值
''' 函数没有返回值,默认返回 None 函数执行过程中遇到return,则终止,下面代码永远不会执行 可以返回任意类型 '''
需要一个变量去接收
示例: # 让用户输入一段字符串,计算字符串中有多少A字符的个数。有多少个就在文件a.txt中写多少个“嘻嘻嘻”。 def get_char_count(data): sum_counter = 0 for i in data: if i == 'A': sum_counter += 1 return sum_counter def write_file(line): if len(line) == 0: return False # 函数执行过程中,一旦遇到return,则停止函数的执行。 with open('a.txt',mode='w',encoding='utf-8') as f: f.write(line) return True content = input('请输入:') counter = get_char_count(content) write_data = "嘻嘻嘻" * counter status = write_file(write_data) if status: print('写入成功') else: print('写入失败')
5.2 参数相关
-
位置参数 : (调用函数并传入函数)
-
关键字传参:
def func(num1,num2) print(num1,num2) func(num1=1,num2=2)
位置传参和关键字传参可以混合使用:
######## 位置传参一定要在关键字传参前面 ###########
-
默认参数 (默认参数推荐用不可变类型,慎用可变类型)
def func(a1,a2,a3=1,a4=2) print(a1,a2,a3,a4) func(11,22) #a3和a4 已有默认参数,所以不必再定义参数 func(11,22,a3=10,a4=100) #再次定义参数,覆盖前面的参数
-
当默认参数数可变类型时
#注意一 def func(a,b=[]): b.append(a) return b v1 = func(1) v2 = func(2,[11,22]) v3 = func(3) print(v1,v2,v3) #[1,3] [11,22,2] [1,3] #注意二: def func(a,b=[]): b.append(a) print(b) func(1) #[1] func(2,[11,22]) #[11,22,2] func(3) #[1,3]
-
-
万能参数(打散)
-
*args:可以接收任意个数的位置参数,并将其转换为元组
-
调用函数无*
def func(*args): print(args) func(1,2,3) #打印func后内容,里面可以是列表集合等
-
调用函数有*
def func(*args): print(args) func(*(1,2,3,4)) # 不管里面的内容是列表/集合都打印成元组,当里面内容为字典时,打印内容为字典的key(键)
-
-
**kwargs : 可以接收任意个数的关键字参数,并将其转换为字典
-
调用函数无**
def func(**kwages): print(kwages) func(k1=1,k2=2) #{'k1': 1, 'k2': 2}
-
调用函数有**
def func(**kwages): print(kwages) func(**{'k1':1,'k2':2}) #后面内容只能是字典
-
-
-
仅限关键字参数
def func(a,b,*args,c): print(a,b) print(c) func(1,2,3,4.c=222) 打印:1,2 222
-
*的作用
a,b,*c = (1,2,3,4,5,6,7) print(a,b,c) # 1 2 [3,4,5,6,7] a,*b,c = [11,22,33,44,55,66,77] print(a,b,c) # 11 [22, 33, 44, 55, 66] 77 a,*b,c = range(10) print(a,b,c) # 0 [1, 2, 3, 4, 5, 6, 7, 8] 9
5.3 作用域 &函数嵌套
-
python中
-
py文件 : 全局作用域
-
函数 : 局部作用域
- 一个函数就是一个作用域
-
作用域查找数据规则 : 优先在自己的作用域查找数据,自己没有再去上一级查找,然后上上级,直到全局,全局没有就报错
#示例1: x = 10 def func(): x = 8 print(x) # 8 def x1(): print(x) # 9 x = 9 x1() x = 10 print(x) # 10 func() #示例2: x = 10 def func(): x = 8 print(x) # 8 def x1(): print(x) # 8 x1() x = 9 x1() # 9 x = 10 print(x) # 10 func()
-
-
子作用域中只能找到父级中的值,默认无法重新为父级中的变量进行赋值. (globol / nonlocal 可以强制做)
-
global : 找到并改变全局中的变量
# 示例 name = "老男孩" def func(): name = 'alex' def inner(): global name name = 999 inner() print(name) # 'alex' func() print(name) # 999
# 声明全局中存在这个变量 def func(): global name nmae = 'alex' func() print(name) # alex
-
nonlocal : 找到并改变上一级中的变量
#示例: name = "老男孩" def func(): name = 'alex' def inner(): nonlocal name name = 999 inner() print(name) # 999 func() print(name) # "老男孩"
-
补充:
-
全局变量以后必须全部是大写
USER_LIST = [11,22,3] def func(): name = 'asdf' USER_LIST.append(12) USER_LIST.append(name) func() print(USER_LIST)
-
-
-
5.4 函数小高级
-
函数名当做变量来使用:
def func(): print(123) v1 = func #指向的是同一内存地址 v1()
#注意:不带括号指向的是内存地址,带括号是调用函数 def func(): return 123 func_list1 = [func,func,func] func_list2 = [func(),func(),func()] print(func_list1) # 打印的是内存地址 print(func_list2) #打印的是 : [123,123,123] 调用函数 info = { 'k1':func, #内存地址 'k2':func(), # 调用函数 } print(info)
-
函数可以当做参数进行传递
结果为: 666 none none
5.5 lambda 表达式 (也叫匿名函数)
用于表示简单的函数
注意:列表所有方法的返回值基本都为none,字符串所有方法的返回值基本都返回新值
5.6 内置函数
-
其他:
-
len / open / id / range / type /
-
all 可迭代对象中全部是true 才是true
l1 = [1,'alex','',0] print(all(l1)) # false
-
any 可迭代对象中有一个为true就是true
l1 = [0,'',1,'alex'] print(any(l1)) # true
-
repr 返回一个对像的string形式
s1 = 'alex' print(s1) # alex print(repr(si)) # 'alex'
-
zip 拉链方式
lis = [1,2,3,4,5] tu = ('a','b','c') s1 = 'alex' obj = zip(lis,tu,s1) print(obj) # 得到是一个迭代器 print(list(obj)) # [(1, 'a', 'a'), (2, 'b', 'l'), (3, 'c', 'e')]
-
-
输入输出 :
-
print / input
print(1,2,3,4,sep = '-') # 1-2-3-4
-
-
强制转换
-
dict / list / tuple / int / str / bool / set
-
dict 创建字典的几种方式
-
直接创建
-
元组的解构
dic1 = dict([(1,'one'),(2,'two'),(3,'three')]) dic2 = dict(one=1,two=2) print(dic1) # {1: 'one', 2: 'two', 3: 'three'} print(dic2) # {'one': 1, 'two': 2}
-
-
reversed 返回的是一个翻转的迭代器
l = [i for i in range(10)] obj = reversed(l) print(obj) # 得到的的是一个迭代器 print(l) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(obj)) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
-
-
编码相关
-
Chr , 将十进制数字转换成Unicode编码中的对应字符串
v = char(99) print(v) # c
-
ord , 根据字符在Unicode编码中找到其对应的十进制
con = ord('中国') print(con) # 20013
-
-
数学相关
-
abs() 绝对值
-
float() 转换为浮点型(小数)
-
max() 找到最大值
-
sum() 求和
-
round() 返回浮点数x的四舍五入值
print(round(12.238,2)) #12.24 print(round(12.234,2)) # 12.23
-
pow() 求一个数的幂
v = pow(2,3) print(v) # 2**3 = 8
-
divmod() 两数相除的商和余数
a,b = divmod(103,5) print(a,b) # a=20 b=3
# 通过分页对数据进行展示 """ 要求: 每页显示10条数据 让用户输入要查看的页面:页码 """ USER_LIST = [] for i in range(1,836): temp = {'name':'啦啦啦-%s' %i,'email':'123%s@qq.com' %i } USER_LIST.append(temp) # 数据总条数 total_count = len(USER_LIST) # 每页显示10条 per_page_count= 10 # 总页码数 max_page_num,a = divmod(total_count,per_page_count) if a>0: max_page_num += 1 while True: pager = int(input('要查看第几页:')) if pager < 1 or pager > max_page_num: print('页码不合法,必须是 1 ~ %s' %max_page_num ) else: """ # 第1页:USER_LIST[0:10] -> 0123456789 # 第2页:USER_LIST[10:20] # 第3页:USER_LIST[20:30] """ start = (pager-1) * per_page_count end = pager * per_page_count data = USER_LIST[start:end] for item in data: print(item)
-
-
进制转换相关
-
bin() 将十进制转换成二进制
-
oct() 将十进制转换为八进制
-
hex() 将十进制转换为十六进制
-
int() 将其他进制转换为十进制
# 二进制转化成十进制 v1 = '0b1101' result = int(v1,base=2) print(result) # 八进制转化成十进制 v1 = '0o1101' result = int(v1,base=8) print(result) # 十六进制转化成十进制 v1 = '0x1101' result = int(v1,base=16) print(result)
#请将 ip = "192.168.12.79" 中的每个十进制数转换成二进制: # 0010100100001010010001010010001010010 -> 十进制的值 ip = "192.168.12.79" ip_list = ip.split('.') lis = [] for i in ip_list: data = bin(int(i)) con = data.replace(data[:2],'0'*(8-len(data[2:]))) lis.append(con) mes = ''.join(lis) result = int(mes,base = 2) print(result)
-
-
括号内带 key
-
sorted 排序
l1 = [22, 33, 1, 2, 8, 7,6,5] l2 = sorted(l1) print(l2) # [1, 2, 5, 6, 7, 8, 22, 33] l2 = [('大壮', 76), ('雪飞', 70), ('纳钦', 94), ('张珵', 98), ('b哥',96)] print(sorted(l2,key= lambda x:x[1])) # 返回的是一个列表,默认从低到高 # [('雪飞', 70), ('大壮', 76), ('纳钦', 94), ('b哥', 96), ('张珵', 98)] print(sorted(l2,key= lambda x:x[1],reverse=True)) # 从高到低 # [('张珵', 98), ('b哥', 96), ('纳钦', 94), ('大壮', 76), ('雪飞', 70)]
-
min 取最小值 (max的用法一样)
# 示例1: 以绝对值的方式取最小值: l1 = [33, 2, 3, 54, 7, -1, -9] print(min(l1,key = abs) # 1 # 示例2: dic = {'a': 3, 'b': 2, 'c': 1} print(min(dic)) # min 会默认按照字典的键去比较 # 结果得到 a (按照ASCII码对照表的大小) print(min(dic,key = lambda a: dic[a])) # c print(min(dic.values(),key=lambda x:x)) # 1
-
总结:凡是可以加key的,它会自动的将可迭代的对象中的每个元素按照顺序传入key对应的函数中,返回的是循环的那个元素
-
-
通过list取值的内置函数
- reversed
- zip
- filter
- map
5.7 高级一点的内置函数 (面试题相关)
-
map : 循环每个元素(第二个参数),然后让每个元素执行函数(第一个参数),将每个函数执行的结果保存到新的列表中,并返回.(相当于列表推导式的循环模式)
v1 = [11,22,33,44] result = map(lambda x:x+100,v1) #将列表里元素每个都加上100 print(list(result)) # 特殊
-
filter : 筛选(相当于列表推导式的筛选模式)
v1 = [11,22,33,'asd',44,'xf'] def func(x): if type(x) == int: return True return False result = filter(func,v1) print(list(result)) # [11, 22, 33, 44] #也可简写成如下: result = filter(lambda x: True if type(x) == int else False ,v1) print(list(result)) # 或 result = filter(lambda x: type(x) == int ,v1) print(list(result)) # 示例二: ret = ['1', '2', '60', '', '5', '4', '3','',''] ret = filter(lambda n:n,ret) print(list(ret)) # 出除了列表里的空字符串,并没有改变里面元素的位置
-
reduce : 将多个元素变成一个元素
import functools #导入一个模块 v1 = ['wo','hao','e'] def func(x,y): return x+y result = functools.reduce(func,v1) print(result) result = functools.reduce(lambda x,y:x+y,v1) print(result)
5.8 函数中高级
-
函数可以作为返回值
面试题相关:
-
闭包
-
什么是闭包:
- 闭包只能存在嵌套函数中
- 内层函数对外层函数非全局变量的应引用,就会形成闭包
- 被引用的非全局变量也称作自由变量,这个变量会与内层函数产生一个绑定关系
- 自由变量不会在内存中消失
- 作用:保证数据的安全
-
-
递归 :
- 最大深度是1000:为了节省内存空间,不让用户无限使用内存空间
#递归打印斐波那契数 def func(a,b): # 1 # 1 # 2 # 3 # 5 print(b) func(b,a+b) func(0,1)
5.9 装饰器
- 完全遵循开放封闭原则:
- 对代码的拓展示开放的
- 对源码的修改是封闭的
-
装饰器编写的格式
- 在不改变原函数内部代码和调用方式的基础上,在函数执行之前和之后自动执行某个功能
def 外层函数(参数) def 内层函数(*args,**kwargs) #函数执行之前 data= 参数(*args,**kwags) #函数执行之后 return data return 内层函数
-
应用
def func(arg): def inner(): v = arg() return v return inner # 第一步:执行func函数并将下面的函数当做参数进行传递, 相当于:func(index) # 第二步: 将func返回的值重新赋值给下面的函数名 index = func(index) @func def index(): print(123) return 666 ret = index() print(ret) # 先打印 123 ,在打印 666
#示例:计算函数执行时间 import time def base(func): def inner(): start_time = time.time() --->#函数执行之前 v= func() end_tme = time.time() ---->#函数执行之后 print(end_time-start_time) return v return inner @base def func1(): time.sleep(2) # 函数执行延缓2秒 print(123) func1() @base def func2(): time.sleep(1) print(456) func2()
-
关于返回值
def x1(func): def inner(*args,**kwargs): data = func(*args,**kwargs) return data return inner #func函数带括号,执行 f1 函数,先打印'123',先将666返回给data,data再返回给v1 @x1 def f1(): print(123) return 666 v1 = f1() # 得到的是inner函数的返回值 print(v1)
-
关于前后
def base(func): def inner(*args,**kwargs): print('函数调用之前') data = func(*args,**kwargs) #执行原函数并获取返回值 print('调用原函数之后') return data return inner @base def index(): print(123) ret= index() print(ret) # None
-
带参数的装饰器
-
基本格式
def base(counter): def wrapper(func): def inner(*args,**kwargs): data = func(*args,**kwargs) # 执行原函数并获取返回值 return data return inner return wrapper @base(9) def index(): pass #先执行base函数,然后将返回值wrapper返回,变成不带参数的装饰器
-
面试相关
#写一个带参数的函,实现:参数是多少,被装饰的函数就要执行多少次,返回最后一次执行的结果 def base(counter): def wrapper(func): def inner(*args,**kwargs): for i in range(counter): data = func(*args,**kwargs) # 执行原函数并获取返回值 return data return inner return wrapper @base(5) def index(): return 8 v = index() print(v)
-
5.6.0 推导式
-
列表推导式(也叫列表生成式)
-
用一行代码构建一个比较复杂有规律的列表
-
基本格式
v1 = [i for i in 可迭代对象] v2 = [i for i in 可迭代对象 if 条件]#条件为true才进行append
#示例 v1 = [99 if i>5 else 66 for i in range(10)] v2 = [lambda : 100 for i in range(10)] result = v2[9]() # 100 v3 = [lambda :i for i in range(10)] result = v3[5]() # 9 v4 = [lambda x:x*i for i in range(10)] # 新浪微博面试题 # 1.请问 v4 是什么? 函数地址 # 2.请问 v4[0](2) 的结果是什么? 18 def num(): return [lambda x:i*x for i in range(4)] # num() -> [函数,函数,函数,函数] print([ m(2) for m in num() ]) # [6,6,6,6]
-
-
集合推导式
v1 = { i for i in 'alex' }
-
字典推导式
v1 = { 'k'+str(i):i for i in range(10) }
-
生成器推导式:
# def func(): # result = [] # for i in range(10): # result.append(i) # return result # v1 = func() v1 = [i for i in range(10)] # 列表推导式,立即循环创建所有元素。 print(v1) # def func(): # for i in range(10): # yield i # v2 = func() v2 = (i for i in range(10)) # 生成器推导式(非元组推导式),创建了一个生成器,内部循环为执行。
第六章 : 模块(类库)
穿插:
- py2:
- xrange:不会再内存中立即创建,而是在循环时,边循环边创建.
- range:在内存中立即把所有的值建立
- py3:
- range : 不会再内存中立即建立,而是在循环时边循环边创建
- py3中没有xrange
- 对于包的定义:
- py2:必须得有
__init__
.py文件 - py3:不需要,但建议每次都加上
- py2:必须得有
6.0 模块的基本认识
- 为什么要有模块
- 拿来主义,提高开发效率
- 便于管理维护
- 什么是脚本:脚本就是py文件,长期保存代码的文件
-
内置模块
- 内置模块是python自带的功能,在使用内置模块相应的功能时,需要先导入再使用
-
第三方模块 :
- 下载-->安装-->使用
1.找到python所在的根目录-->再找到Scripts目录-->最后找到pip.exe 2.把pip.exe所在的目录添加到环境变量中 3.pip install 要安装的模块名称 #pip install xlrd #安装完成后,如果导入不成功 - 重启pycharm - 安装错了
-
自定义模块
-
自己写一个模块(一个py文件): aaa.py
def f1(): prinrt('f1') def f2(): print('f2')
-
在另一个py文件中调用模块中的功能 :a1.py
#调自定义模块中的功能 import aaa aaa.f1() aaa.f2()
-
运行
a1.py
-
-
什么是模块
- py文件 写好了的,对程序员提供某方面功能的文件
-
什么是包
- 文件夹,储存了多个py文件的文件夹
- 如果导入的是一个包,这个包里的模块默认是不能用的
- 导入一个包相当于执行了
__init__
.py文件中的内容
6.1 模块的调用
- 示例一:
示例:
# xxx.py
def show():
print('nihao')
def func():
pass
print(111)
#导入模块,加载此模块中的所有值到内存(一)
import xxx
print(222)
##调用模块中的函数
xxx.func()
#导入模块(二)
from xxx import func,show
from xxx import func
from xxx import *
func()
#导入模块(三)
from xxx import func as f #起别名
def func():
print(222)
f()
-
示例二:
xxxxxx #(某个文件夹) -jd.py #里面有个f1函数 -tb.py -pdd.py
import xxxxxx.jd jd.f1()
from xxxxxx import jd jd.f1()
from xxxxxx.jd import f1 f1()
- 第一次导入模块执行三件事:
- 在内存中创建一个以模块名命名的名称空间
- 执行此名称空间所有的可执行代码
- 通过 模块. 的方式引用模块里面的代码
- 总结:
- 模快和要执行的py文件在同一目录且需要模块中的很多功能时,推荐使用:import 模块
- 其他推荐:from 模块 import 模块 模块.函数()
- 其他推荐:from 模块.模块 import 函数 函数()
6.1 包的导入
-
导入一个包(文件夹)相当于执行了这个包下的
__init__
文件,并不相当于把这个包下的所有文件都导入进来了
6.2 内置模块
1.random
- random,randint
import random
def get_random_code(length = 6):
data = []
for i in range(length):
v = random.randint(65,90)
data.append(chr(v))
return ''.join(data)
code = get_random_code()
print(code)
import random # 导入一个模块
v = random.randint(起始,终止) #得到一个随机数
-
random.unifrom
import random a = random.unifrom(3,5) print(a) # 返回的是3-5之间的一个浮点数
-
random.random
print(random.random()) #得到是一个0-1之间的浮点数
2.hashlib :
-
作用: ,密文登入验证 / 检验文件的一致性
-
用于加密相关的操作,把一个大的数据切分成不同块,分别对不同的块进行加密汇总的结果,和直接对整体数据加密的结果是一致的
-
将bytes类型字节转化成固定长度的16进制数字组成的字符串
-
不同的bytes利用相同的算法转化的结果一定不同
-
相同的bytes利用相同的算法转化的结果一定相同
-
haslhib 算法不可逆
-
将指定的'字符串'进行加密
import hashlib def get_md5(num): obj = hashlib.md5() # 获取一个加密对象 obj.update(num.encode('utf-8')) # 使用加密对象的update进行加密 return obj.hexdigest() # 通过hexdigest获取加密效果 val = get_md5('某段数字') print(val)
-
加盐 : (让密码更加安全)
import hashlib def get_md5(data): # md5括号内的内容越长,越不容易被破解 obj = hashlib.md5("sidrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8')) obj.update(data.encode('utf-8')) result = obj.hexdigest() return result val = get_md5('123') print(val)
-
应用
import hashlib USER_LIST = [] def get_md5(data): obj = hashlib.md5("12:;idrsicxwersdfsaersdfsdfresdy54436jgfdsjdxff123ad".encode('utf-8')) obj.update(data.encode('utf-8')) result = obj.hexdigest() return result def register(): print('**************用户注册**************') while True: user = input('请输入用户名:') if user == 'N': return pwd = input('请输入密码:') temp = {'username':user,'password':get_md5(pwd)} USER_LIST.append(temp) def login(): print('**************用户登陆**************') user = input('请输入用户名:') pwd = input('请输入密码:') for item in USER_LIST: if item['username'] == user and item['password'] == get_md5(pwd): return True register() result = login() if result: print('登陆成功') else: print('登陆失败')
-
密码 不显示,(只能在终端运行)
import getpass pwd = getpass.getpass('请输入密码') if pwd == '123' print('输入正确')
3. sys
- python解释器相关的数据
-
sys.getrefcount : 获取一个值的应用计数
import sys #导入模块 a = [1,2,3] b = a print(sys.getrefcount(a)) #结果为:3 相当于a被使用了三次
-
sys.getrecursionlimit : python中默认支持的递归数量
import sys print(sys.getrecursionlimit()) # 结果为 :1000 修改最大递归次数: import sys sys.setrecursionlimit(10000)
-
sys.stdout.write 类似于print打印
-
换行
-
制表符
-
回到当前行的起始位置
print('1231你好你好你好23 ',end='') print('你好',end='') #由于 的存在,回到了当前行的起始位置,没有换行,只会打印'你好'
-
-
sys.argv : 命令行参数,第一个元素是程序本身路径
#示例: import sys if len(sys.argv) < 3: print('参数不够,请重新运行') else: file_path = sys.argv[1] content = sys.argv[2] with open(file_path,mode='w',encoding='utf-8') as f: f.write(content)
-
sys.path 会自动将当前目录的路径添加到sys.path列表中
# 如果想要引用自定义的模块,要么将这个模块放在当前目录下面,要么手动添加到sys.path中 ''' sys.path 列表中的第一个元素总是当前执行脚本的父目录 '''
-
sys.modules 查看导入了那些模块
4.os
- 处理和操作系统相关的数据
-
os.path.exists(path) , 如果path存在,返回True;如果path不存在,返回False
-
os.path.getsize() 获取文件的大小
a = os.path.getsize(r'D:python全栈网络编程day28oneserver.py') print(a) # 693
-
os.path.abspath() : 获取一个文件的绝对路径
path = '某个需要查看路径的文件' import os v1 = os.path.abspath(path) print(v1)
-
os.path.dirname : 获取路径的上级目录(不判断路径是否存在)
import os v = r"C:python36新建文件夹python36.exe D:/第三周/day14.py" print(os.path.dirname(v)) #C:python36新建文件夹python36.exe D:/第三周 一级一级往上走
-
os.path.split 把路径中的路径名和文件名切分开,结果是元组
import os res = os.path.split(r'd:/aaa/bbb/ccc/a.txt') print(res) # ('d:/aaa/bbb/ccc', 'a.txt')
-
os.path.join : 路径的拼接
import os path = "C:python36新建文件夹python36.exe" v = 'n.txt' result = os.path.join(path,v) print(result) #C:python36新建文件夹python36.exe .txt result = os.path.join(path,'n1','n2','n3') print(result) #C:python36新建文件夹python36.exe 1 2 3
-
os.listdir :查看一个目录下所有的文件(第一层)
import os result = os.listdir(r'D:untitled') for i in result: print(i)
-
os.walk : 查看一个目录下所有的文件(所有层)
import os result = os.walk(r'D:untitled') for a,b,c in result: # a,正在查看的目录 b,此目录下的文件夹 c,此目录下的文件 for item in c: path = os.path.join(a,item) print(path)
-
os.path.basename() :获取文件名称
返回path最后的文件名,如果path以 / 结尾,就返回空值
a = os.path.basename(r'D:python全栈网络编程day28four')
print(a) # 结果为: four
a = os.path.basename('D:python全栈网络编程day28four/')
print(a) # 结果:啥都没有,空
- 转义 : 'r'
v1 = r"D:codes21day14
1.mp4" (推荐)
print(v1)
# D:codes21day14
1.mp4
v2 = "D:\code\s21day14\n1.mp4" (不推荐)
print(v2)
# D:codes21day14
1.mp4
-
os.makedirs 创建目录和子目录
-
os.rename 重命名
import os
os.rename('某个文件的名字','想要修改后的名字')
#练习:
import os
#1.读取文件大小(字节)
file_size = os.stat('某个文件').st_size
#2. 一点一点读取文件
read_size = 0
with open('某个文件',mode='rb') as f1,open('将要写入的文件',mode='wb') as f2:
while read_size < file_size:
chunk = f1.read(1024) #每次最多去读取1024字节
f2.write(chunk)
read_size += len(chunk)
val = int(read_size / file_size * 100) #查看打印进度
print('%s%%
' %val ,end='')
-
删除
# 删除文件 os.remove('文件名') # 删除目录(必须是空目录) os.removedirs('目录名')
-
os.getcwd 查看工作目录
os.chdir 改变工作目录
-
os.urandom(16) 获取一个随机的16字节大小的字符串
```python
# 和执行操作系统命令相关
os.popen/os.system
import os
os.system('dir')
ret = os.popen('dir')
print(ret.read())
```
5.json&pickle
-
序列化:将内存中的数据转换成字符串,用以保存文件或通过网络传输
-
反序列化:从文件或网络中获取的数据转换成内存中原来的数据类型
-
json : 一个特殊的字符串 [长得像列表/字典/字符串/数字/真假]
- 优点:所有语言通用;缺点:只能序列化基本的数据类型
- json.dumps 序列化
- json.loads 反序列化
- 通常都是一次性读 一次性写,用于存储或者网络传输
import json #序列化:将python的值转换为json格式的字符串 v = [11,22,{'k1':'v1'},True,'ggg'] v1 = json.dumps(v) print(v1) #"[11, 22, {"k1": "v1"}, true, "ggg"]" #反序列化 : 将json格式的字符串转换成python的数据类型 v2 = '["alex",123]' print(type(v2)) #字符串类型 v3 = json.loads(v2) print(v3,type(v3)) #['alex', 123] <class 'list'>
-
字典或列表中如有中文,序列化时想要保留中文显示
v = {'k1':'alex','k2':'李杰'} import json val = json.dumps(v,ensure_ascii=False) print(val)
-
注意:
- json 最外层必须是容器类的,如列表/字典,元组会被转换为列表.
- 里面的内容可以是:str int bool list tuple 集合不能存在于json中
- 字串必须使用双引号(" ")连接
# 将json类型的结果写到文件中 import json with open('a.txt',mode='w',encoding='utf-8') as f: json.dumps([1,2,3],f,ensure_ascii=False) # 从文件中读取json类型结果 with open('a.txt',mode='r',encoding='utf-8') as f: con = json.loads(f) print(con)
# 把需要序列化的对象.通过多次序列化的方式, 用文件的write方法,把多次序列化后的json字符串,写到文件中. with open('b.txt',mode='at',encoding='utf-8') as f: f.write(json.dumps([1,2,3]) + ' ') f.write(json.dumps([4,5,5]) + ' ') # 把分次序列化的json字符串,反序列化回来 with open('b.txt',mode='rt',encoding='utf-8') as f: for x in f: print(json.loads(x.strip()))
-
pickle:优点:python中所有的东西都能被他序列化(转换为bytes类型) 缺点:序列化的内容只有python认识
-
dumps loads 只能用于网络传输
l1 = [1, 2, 3] import pickle st = pickle.dumps(l1) print(st) # b'x80x03]qx00(Kx01Kx02Kx03e.' l2 = pickle.loads(st) print(l2,type(l2)) # [1, 2, 3] <class 'list'>
-
dump load 直接写入文件(还可以写入函数名,对象)
-
6.shutil
-
删除目录
import shutil shutil.rmtree('要删除的目录')
-
重命名
import shutil shutil.move('原目录','修改后的目录')
-
压缩文件 shutil.make_archive
import shutil shutil.make_archive('要压缩的文件','文件的后缀名(如zip)','要压缩到的路径') #示例: import shutil shutil.make_archive('xxx','zip','D:第三周')
-
解压文件 shutil.unpack_archive
import shutil shutil.unpack_archive('要解压的文件',extract_dir=r'D:codexxxxxxxxxx',format='zip')
示例: import os import shutil from datetime import datetime ctime = datetime.now().strftime('%Y-%m-%d %H-%M-%S') # 1.压缩lizhongwei文件夹 zip # 2.放到到 code 目录(默认不存在) # 3.将文件解压到D:x1目录中。 if not os.path.exists('code'): #判断路径是否存在 os.makedirs('code') shutil.make_archive(os.path.join('code',ctime),'zip','D:codes21day16lizhongwei') #压缩文件 file_path = os.path.join('code',ctime) + '.zip' #两个路径拼接 shutil.unpack_archive(file_path,r'D:x1','zip') #解压文件
-
拷贝文件
shutil.copy2('原文件', '现文件')
-
拷贝目录
shutil.copytree("原目录", "新目录", ignore=shutil.ignore_patterns("*.pyc")) # ignore后面是不拷贝的内容
-
获取磁盘使用空间
total, used, free = shutil.disk_usage(".") print("当前磁盘共: %iGB, 已使用: %iGB, 剩余: %iGB"%(total / 1073741824, used / 1073741824, free / 1073741824))
7.time&datetime
- UTG/GMT 世界时间
- 本地时间 本地时区的时间
-
time :
- time.time() 时间戳(获取当前时间) 从1970-1-1 00:00 后走过的秒数
- time.sleep(8) 等待的秒数
import time now = time.localtime() print(now) print(now.tm_year) # 获取当前时间的年份 print(now.tm_mon) # 获取当前时间的月份 print(now.tm_mday) # 获取当前时间的几号
-
datetime
-
获取datetime格式时间
import time from datetime import datetime,timezone,timedelta v1 = datetime.now() # 获取当前本地时间 print(v1) # 2019-04-18 16:39:31.802269 tz = timezone(timedelta(hours=7)) #当前东7区时间 (如要获取西7区时间 hours=-7) v2 = datetime.now(tz) print(v2) #2019-04-18 15:39:31.802269+07:00 (中国在东8区,所以慢一个小时) v3 = datetime.utcnow() #当前UTC时间(世界时间) print(v3) #2019-04-18 08:39:31.802269 (比中国时间慢8个小时)
-
把datetime格式转换成字符串 (strftime)
import time from datetime import datetime,timezone,timedelta v1 = datetime.now() val = v1.strftime("%Y-%m-%d %H:%M:%S") #(年-月-日 时:分:秒) print(val) #2019-04-18 16:48:29
-
字符串转成datetime格式 datetime.strptime
import time from datetime import datetime,timezone,timedelta v1 = datetime.strptime('2019-4-18','%Y-%m-%d') print(v1,type(v1)) # 2019-04-18 00:00:00 <class 'datetime.datetime'>
-
datetime时间的加减
from datetime import datetime,timedelta v1 = datetime.strptime('2008-08-08','%Y-%m-%d') v2 = v1-timedelta(days=150) data = v2.strftime('%Y-%m-%d') print(data) #2008-03-11 #先转换为datetime格式进行加减,然后转换为字符串格式打印出来
-
时间戳和datetime的关系
import time from datetime import datetime,timezone,timedelta ctime = time.time() print(ctime) # 1555578896.8276453 v1 = datetime.fromtimestamp(ctime) print(v1) # 2019-04-18 17:14:56.827645 v1 = datetime.now() val = v1.timestamp() print(val) #1555579030.002739
-
8.第三方模块: requests
import requests
# 获取网页源码
ret = requests.get('一个网址 ').strip() # 输入网址后加一个空格
print(ret.content) # 以字节的方式去显示,中文显示为字符
print(ret.text) # 以文本的方式去显示
6.3异常处理
示例:
#写函数去,接受一个列表。列表中都是url,请访问每个地址并获取结果。
import requests
def func(url_list):
result = []
try:
for url in url_list:
response = requests.get(url)
result.append(response.text)
except Exception as e:
pass
return result #['http://www.baidu.com'] (中国无法访问谷歌)
def func2(url_list):
result = []
for url in url_list:
try:
response = requests.get(url)
result.append(response.text)
except Exception as e:
pass
return result #['http://www.baidu.com','http://www.bing.com']
func(['http://www.baidu.com','http://www.google.com','http://www.bing.com'])
6.4 迭代器&生成器
- 迭代器
- 优点:节省内存。惰性机制。
- 缺点:不直观,速度相对慢,操作方法单一,不走回头路。
- 对某种对象(str/lsit/tuple/dict/set类创建的对象)中的元素进行逐一获取,表象:具有
__next__
方法且每次调用都获取可迭代对象中的元素 - 列表转换成迭代器
- v1 = iter([1,2,3,4])
- v2 = [1,2,3,4].
__iter__
()
- 迭代器想要获取每个元素:反复调用val = v1.
__next__
()
#示例:
v1 = "alex"
v2 = iter(v1)
while True:
try:
val = v2.__next__()
print(val)
except StopIteration as e:
break
-
直到报错:StopIteration错误,表示迭代已经完毕
-
如何判断一个对象是否是迭代器 : 内部是否有
__next__
方法 -
for 循环
v1 = [11,22,33,44] # 1.内部会将v1转换成迭代器 # 2.内部反复执行 迭代器.__next__() # 3.取完不报错 for item in v1: print(item)
-
可迭代对象
- 内部具有
_iter__
方法且返回一个迭代器 - 可以被for 循环
- 优点:操作方法多,操作方法灵活,直观
- 缺点:占用内存
- 内部具有
-
生成器 (函数的变异)
-
获取生成器的三种方式
- 生成器函数
- 生成器表达式
- python内部提供的一些
-
生成器的本质就是迭代器,
- 唯一区别:生成器是我们自己用python代码构建的数据结构,迭代器都是提供的或者是转化得来的
-
生成器函数 (内部是否包含yield)
def func(): print('F1') yield 1 print('F2') yield 2 print('F3') #函数内部代码不会执行,返回一个生成器对象 v1 = func() #生成器可以被for 循环,一旦开始循环函数内部代码就开始执行 for item in v1: print(item) # F1 1 F2 2 F3
# yield from 优化了内层循环,提高了效率 def func(): l1 = [1, 2, 3, 4, 5] yield from l1 ret = func() print(next(ret)) # 取列表里的一个元素 1 # yield def func(): l1 = [1, 2, 3, 4, 5] yield l1 ret = func() print(next(ret)) #得到的是一个列表
-
总结:
- 函数中如果存在yield,那么该函数就是一个生成器函数,调用生成器函数会返回一个生成器,生成器只有被for循环时,生成器函数内部代码才会执行,每次循环都会获取yield返回的值
- return:函数中只存在一个return结束函数,并且给函数的执行者返回值
- yield:只要函数中有yield那么他就是生成器函数了
- 生成器函数可以存在多个yield,yield不会结束生成器函数,一个yield对应一个next
-
第七章 : 面向对象
7.0 面向对象基础
- 什么是类:具有相同方法和属性的一类事物
- 什么是对象,实例:一个拥有具体属性值和动作的具体个体
- 实例化:从一个类得到一个具体对象的过程
- 类 ---> 实例化 ---> 对象
- 类和对象的关系
- 类是一个大范围,是一个模子,约束了事物有哪些属性,但是不能约束具体的值
- 对象是一个具体的值,是模子的产物,遵循了类的约束,同时给属性附上具体的值
- 实例化所经历的步骤:
- 类名() 之后的第一个事儿: 先开辟一块内存空间
- 调用
__init__
,把空间的内存地址作为self参数传递到函数内部 - 所有的这一个对象需要使用的属性都需要和self关联起来
- 执行完
__init__
中的逻辑之后,self变量会自动的被返回到调用处(发生实例化的地方)
-
应用场景:
- 遇到很多函数,需要给函数进行归类和划分 [封装]
-
基本格式
class Person: def __init__(self,name,sex,job,age): self.name = name self.sex = sex self.job = job self.age = age obj = Person('alex','nan','IT','30') # 实例化一个obj对象 print(obj.__dict__) # {'name': 'alex', 'sex': 'nan', 'job': 'IT', 'age': '30'} obj.name = 'wusir' # 修改属性 obj.money = 1000 # 增加属性 del obj.money # 删除属性
-
组合:
-
一个类的对象是另一个类对象的属性
# 查看linux57期的班级所学课程的价格 # 查看python22期的班级所学课程的周期 class Clas: def __init__(self,cname,begint,teacher,course): self.cname = cname self.begint = begint self.teacher = teacher self.course = course class Course: def __init__(self,name,period,price): self.name = name self.period = period self.price = price python = Course('python','6 months',21800) linux = Course('linux','5 months',19800) py22 = Clas('python全栈22期','2019-4-26','小白',python) linux57 = Clas('linux运维57期','2019-3-27','李导',linux) print(py22.course.period) print(linux57.course.price)
-
-
对象的作用
-
存储一些值,以后方便自己使用
class File: def read(self): with open(self.xxx,mode= 'r',encoding = 'utf-8') as f: data = f.read() return data #实例化一个File 类的对象 obj1 = File() #在对象中写一个xxx = 'text.log' obj1.xxx = 'text.log' #通过对象调用类中的read方法,read方法中的self就是obj obj.read()
-
总结:将数据封装到对象,方便使用
-
总结:如果写代码时,函数比较多而乱
-
1.可以将函数归类并放到同一类中
-
2.函数如果有一个反复使用的公共值,则可以放到对象中
-
练习
#循环让用户输入用户名/密码/邮箱.输入完成后再进行打印 class Person: def __init__(self,user,pwd,email): self.username = user self.password = pwd self.email = email user_lisr = [] while Ture: user = input('输入用户名') pwd = input('请输入密码') email = input('请输入邮箱') a = Person(user,pwd,email) user_list.append(a) for item in USER_LIST: temp = "我的名字:%s,密码:%s,邮箱%s" %(item.username,item.password,item.email,) print(temp)
7.2 面向对象的三大特性
1.继承
- 什么时候才能用到继承:
- 多个类中如果有公共的方法,可以放到基类中避免重复编写
# 父类(基类)
class Base:
def f1(self):
pass
# 子类(派生类)
class Foo(Base):
def f2(self):
pass
# 创建一个子类的对象
obj = Foo()
# 执行对象.方法时,优先在自己的类中找,如果没有就是父类中找。
obj.f2()
obj.f1()
# 创建了一个父类的对象
obj = Base()
obj.f1()
-
继承方法中的查找方法的顺序
- self 到底是谁
- self 是哪个创建的,就像从此类开始找,自己没有就找基类
-
父类和子类方法的选择
- 子类的对象如果去调用方法,如果自己有就先调用自己的,自己没有就用父类的,
- 如果自己有还想用父类的:直接在子类的方法中调父类的方法 父类名.方法名(self)
-
继承的其他现象
2.多态 (也叫鸭子模型)
-
多态:一个类表现出的多种形态,实际上是通过继承来完成的
''' 如果狗类继承动物类,猫类也继承动物类 那么猫的对象也是动物类型的,狗的对象也是动物类型的 在这个例子中,动物这个类型表现出了猫和狗的形态 '''
# Python
def func(arg):
v = arg[-1] # arg.append(9)
print(v)
- 什么是鸭子模型?
- 对于一个函数而言,python对于参数的类型不会限制,那么传入参数时就可以是各种类型,在函数中如果有例如:arg.send方法,那么就是对于传入类型的一个限制(类型中必须有send方法).这就是鸭子模型,类似于上述的函数我们认为只要能呱呱叫的就是鸭子(只要有send方法,就是我们想要的类型) -->wusir版
- 在python中,一个类是不是属于某一类型,不仅可以通过继承来完成,还可以是不继承,但是如果这个类满足了某些类型的特征条件,我们就说他长得像这个类型,那么他就是这个类型的鸭子模型 -->女神版
3.封装
-
广义:把属性的方法封装起来,外面就不能直接调用了,要通过类的名字来调用
-
狭义: 把属性和方法藏起来,外面不能调用,只能在内部偷偷调用
class User: def __init__(self,name,pwd): self.name = name self.__pwd = pwd # 私有的实例变量 / 私有的对象属性 alex = User('alex',1234) print(alex.__pwd) # 无法访问 报错 print(alex.pwd) # 报错 ''' 给一个名字前面加上了双下划线的时候,这个名字就变成了一个私有的 所有私有的内容或者名字都不能再类的外部调用只能在类的内部使用 '''
# 从外部调用加双下划线的方法或静态变量 class User: __country = 'china' # 私有的静态变量 __name = 'Alex' def func(self): print(self.__name) # 在类的内部使用的时候,自动把当前这句话所在的类的名字拼在私有变量前完成变形 print(User._User__country) # china User().func() # Alex # __Country -->'_User__Country': 'China'
-
私有的内容不能被子类使用
-
其他语言中的数据级别:
- public 公有的:类内类外都能用,父类和子类都能用 python支持
- protect 保护的:类内能使用,父类子类都能用,类外不能用 python不支持
- private 私有的:本类的类内部能用,其他地方不能用 python支持
7.1 成员
-
实例(对象)
- 实例变量
-
类
- 类变量
- 绑定方法
- 类方法
- 静态方法
- 属性
-
类变量
- 定义:
- 写在类的下一级,和方法同一级
- 访问
- 类.类变量名称
- 对象.类变量名称
####应用示例##### class Base: x = 1 obj.Base() print(obj.x) #先去对象中找,没有再去类中找 1 obj.y = 123 #在对象中添加了一个y=123的变量 print(obj.y) #对象中y=123 123 obj.x = 123 #在对象中添加一个变量x=123 print(obj.x) # 123 print(Base.x) #类中x=1 1
- 总结
- 找变量优先找自己,自己没有找类或基类,修改或赋值只能在自己的内部设置
- 类中的变量是静态变量
- 对象中的变量只属于对象本身,每个对象有属于自己的空间来存储对象的变量
- 当使用对象名去调用某一个属性的时候,会优先在自己的空间中寻找,找不到再去对应的类中寻找,如果类也没有就报错
- 定义:
-
方法(绑定方法)
-
定义:至少有一个self参数
-
执行:先创建对象, 对象.方法()执行
class Foo: def __init__(self): self.name = 111 def func(self,a,b) #绑定方法,至少有一个self参数 print(self.name,a,b) obj = Foo() obj.func(1,2)
-
-
静态方法
-
定义
- @staticmethod装饰器
- 参数无限制
-
执行
- 类.静态方法名()
- 对象.静态方法名 (不推荐)
class Foo: def __init__(self): self.name = 123 def func(self, a, b): print(self.name, a, b) @staticmethod def f1(): #静态方法(可以不用传参数) print(123) obj = Foo() obj.func(1, 2) Foo.f1() obj.f1() # 不推荐
-
-
类方法
-
定义:
- @classmethod装饰器
- 至少有一个cls参数,当前类
-
执行:
- 类.类方法名()
- 对象.类方法名() 不推荐
class Goods: __discount = 0.8 def __init__(self): self.__price = 5 self.price = self.__price * self.__discount @classmethod # 把一个对象的绑定方法修改成一个类方法 def change_discount(cls,new_discount): cls.__discount = new_discount Goods.change_discount(0.6) # 类方法可以通过类名来调用 obj1 = Goods() print(obj1.price) # 3.0 obj1.change_discount(0.5) # 类方法可以通过对象来调用 obj2 = Goods() print(obj2.price) # 2.5 ############# 示例: import time class Date: def __init__(self,year,month,day): self.year = year self.month = month self.day = day @classmethod def today(cls): now_time = time.localtime() date = cls(now_time.tm_year,now_time.tm_mon,now_time.tm_mday) return date date = Date.today() print(date.year) print(date.month) print(date.day)
# 问题: @classmethod和@staticmethod的区别? ''' 一个是类方法,一个是静态方法 定义: 类方法:用@classmethod做装饰器且至少有一个cls参数 静态方法:用@staticmethod做装饰器且参数无限制 调用: 类.方法()直接调用 对象.方法()也可调用 (不推荐) '''
-
-
属性
-
定义:
- @property装饰器:把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接的得到返回值
- 只有一个self参数
-
执行:
- 对象.方法 不加括号
class Foo: @property def func(self): print(123) return 666 obj = Foo() result = obj.func print(result)
# property进阶 class Goods: discount = 0.8 def __init__(self,name,origin_price): self.name = name self.__price = origin_price @property def price(self): return self.__price * self.discount @price.setter def price(self,new_value): if isinstance(new_value,int): self.__price = new_value apple = Goods('apple',5) print(apple.price) # 调用的是被@property装饰的price apple.price = 10 # 调用的是被setter装饰的price print(apple.price)
-
属性的应用
''' 分页并查看页码中的内容 ''' class Page: def __init__(self, total_count, current_page, per_page_count=10): self.total_count = total_count self.per_page_count = per_page_count self.current_page = current_page @property def start_index(self): return (self.current_page - 1) * self.per_page_count @property def end_index(self): return self.current_page * self.per_page_count USER_LIST = [] for i in range(321): USER_LIST.append('alex-%s' % (i,)) # 请实现分页展示: current_page = int(input('请输入要查看的页码:')) p = Page(321, current_page) data_list = USER_LIST[p.start_index:p.end_index] for item in data_list: print(item)
-
-
新式类 / 经典类
class Foo: pass class Foo(object): pass #在py3中这两个的写法是一样的,因为所有的类默认都会继承object类,全部都是新式类 # 如果在python2中这样定义,则称其为:经典类 class Foo: pass # 如果在python2中这样定义,则称其为:新式类 class Foo(object): pass ''' 新式类和经典类的区别: 新式类:继承object ,有super mro ,继承广度优先 查看广度优先的顺序: 类名.mro() 经典类:不继承object,没有super mro ,继承深度优先 '''
7.3 双 __ 方法
-
__init__
初始化方法 -
__new__
用于创建空对象(构建方法)class A: def __new__(cls, *args, **kwargs): obj = super().__new__(cls) # obj = object.__new__(cls) # 第二种写法 print('执行new方法') return obj # 需要将对象返回回去,才能执行init方法 def __init__(self): print('执行init方法') A() 先打印: 执行new方法 再打印: 执行init方法 # 实例化的时候: 先创建一个对象的空间,有一个指针指向类 --> __new__ 调用init --> __init__
-
__call__
对象加括号,执行cal方法格式:
class A: def __call__(self, *args, **kwargs): print('*********') obj = A() print(callable(obj)) # 判断对象是否是可被调用的,如果类中没有call方法,则是False A()() # 对象加() 会自动执行call方法里面的代码 运行结果: True *********
-
__getitem__ __setitem__ __delitem__
class Foo(object): def __setitem__(self, key, value): print(key,value) def __getitem__(self, item): return item + 'uuu' def __delitem__(self, key): pass obj1 = Foo() obj1['k1'] = 123 # 内部会自动调用 __setitem__方法 #打印的结果为 k1 123 val = obj1['xxx'] # 内部会自动调用 __getitem__方法 print(val) # 打印结果为 xxxuuu del obj1['ttt'] # 内部会自动调用 __delitem__ 方法
-
__str__
和__repr__
- 当我们打印一个对象 用%s进行字符串拼接或者str(对象)总是调用这个对象的
__str__
方法 - 如果找不到
__str__
,就调用__repr__
方法 __repr__
不仅仅是__str__
的替代品,还有自己的功能- 用%r 进行字符串拼接 或者用repr(对象)的时候总是调用这个对象的
__repr__
方法
class clas: def __init__(self): self.student = [] def append(self,name): self.student.append(name) def __repr__(self): return str(self.student) def __str__(self): return 'aaa' py22 = clas() py22.append('大壮') print(py22) # aaa print(str(py22)) # aaa print('我们py22班 %s'%py22) # 我们py22班 aaa print('我们py22班 %r'%py22) # 我们py22班 ['大壮'] print(repr(py22)) # ['大壮']
- 当我们打印一个对象 用%s进行字符串拼接或者str(对象)总是调用这个对象的
-
__dict__
class Foo(object): def __init__(self,name,age,email): self.name = name self.age = age self.email = email obj = Foo('alex',19,'xxxx@qq.com') val = obj.__dict__ # 去对象中找到所有变量并将其转换为字典 print(val)
-
上下文管理
class Context: def __enter__(self): print('进入') return self def __exit__(self, exc_type, exc_val, exc_tb): print('推出') def do_something(self): print('内部执行') with Context() as ctx: print('内部执行') ctx.do_something() # 当语法有 with 类() 时,类里面必须包含__enter__方法和__exit__方法;方法__enter__返回的是什么,as后面接收就是什么
-
__len__
class Cls: def __init__(self,name): self.name = name self.students = [] def len(self): return len(self.students) def __len__(self): return len(self.students) py22 = Cls('py22') py22.students.append('杜相玺') py22.students.append('庄博') py22.students.append('大壮') print(py22.len()) # 3 print(len(py22)) # 3 # py22.len() 调用的是def len # len(py22) 调用的是def __len__
-
__base__
查看类继承了哪一个类 -
两个对象的相加
class Foo(object): def __add__(self, other): return 123 obj1 = Foo() obj2 = Foo() val = obj1 + obj2 print(val)obj1 = Foo() obj2 = Foo() val = obj1 + obj2 print(val)
-
__eq__
__gt__
__lt__
class Person(object): def __init__(self,name,age): self.name = name self.age = age def __eq__(self,other): # 两个对象作比较的时候,会自动调用这个方法 print('in eq') def __gt__(self,other): print('in gt') def __lt__(self,other): print('in lt') alex = Person('alex',83) wusir = Person('wusir',74) alex == wusir # == 符号刚好会调用alex对象对应类的__eq__方法,wusir会被当做other参数传入方法 alex < wusir # 执行__gt__方法 alex > wusir # 执行__lt__方法
特殊成员:就是为了能快速实现执行某些方法而生
7,4 内置函数补充
-
type:查看类型
class Foo: pass obj = Foo() if type(obj) == Foo: print('obj是Foo类的对象') # 判断obj是否是foo的对象
-
issubclass 判断是否是某个类的基类
class Base: pass class Base1(Base): pass class Foo(Base1): pass class Bar: pass print(issubclass(Bar,Base)) # false print(issubclass(Foo,Base)) # true
-
isinstance 判断对象是否是某个类或其基类的实例对象
class Base(object): pass class Foo(Base): pass obj = Foo() print(isinstance(obj,Foo)) # 判断obj是否是Foo类或其基类的实例(对象) # True print(isinstance(obj,Base)) # 判断obj是否是Foo类或其基类的实例(对象) # True
-
super
class A(object): def func(self): print('A') class B(A): def func(self): super().func() print('B') class C(A): def func(self): super().func() print('C') class D(B,C): def func(self): super().func() super(D,self).func() print('D') D().func() # 结果: A C B D ''' super 是按照mro顺序(D-->B-->C--A)来寻找当前类的下一个类 在D类中的super还可以写成: super(D,self).func(),py2中的新式类必须这样写 ''' # 示例: class User: def __init__(self,name): self.name = name class VIPUser(User): def __init__(self,name,level,strat_date,end_date): # User.__init__(self,name) super().__init__(name) # 推荐的 # super(VIPUser,self).__init__(name) self.level = level self.strat_date = strat_date self.end_date = end_date 太白 = VIPUser('太白',6,'2019-01-01','2020-01-01') print(太白.__dict__)
- 结论:
- 在py3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名中方法
- 在py2中的新式类中,需要我们主动传递参数super(子类的名字,子类的对象).函数名()
7.5 异常处理
-
基本格式
try: pass except Exception as e: # Exception : 所有报错信息都能接收 pass
finally:
try: int('asdf') except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。 finally: print('最后无论对错都会执行') # #################### 特殊情况 ######################### def func(): try: # v = 1 # return 123 int('asdf') except Exception as e: print(e) # e是Exception类的对象,中有一个错误信息。 return 123 finally: print('最后') func() #函数中有return时,finally也会执行
-
主动触发异常
try: int('123') raise Exception('xxxxx') # 代码中主动抛出异常 except Exception as e: print(e) # 打印的结果是Exception括号内抛出的异常
-
自定义异常
class MyException(Exception): pass try: raise MyException('asdf') except MyException as e: print(e)
class MyException(Exception): def __init__(self,message): super().__init__() self.message = message try: raise MyException('asdf') except MyException as e: print(e.message)
7.6 可迭代对象
-
表象:可以被for循环对象就可以成为是可迭代对象
class Foo: pass obj = Foo()
-
如何让一个对象变成可迭代对象
- 在类中实现
__iter__
方法且返回一个迭代器(生成器)
class Foo: def __iter__(self): return iter([1,2,3,4]) obj = Foo() class Foo: def __iter__(self): yield 1 yield 2 yield 3 obj = Foo()
- 在类中实现
-
只要能被for循环就是去看他内部的iter方法
7.7 约束
import sys
class Payment: # 这个类为抽象类,为了规范子类必须实现的父类的同名方法
def pay(self,money): # 需要传参
raise NotImplementedError('请在子类中重写pay方法') # 主动抛出异常
class Wechat(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过微信支付%s钱成功' %(self.name,money))
class Apple(Payment):
def __init__(self,name):
self.name = name
def pay(self,money): # 通过继承的关系来判断方法名是否一样,如果与归一化设计的方法不同则会抛出异常
print(print('%s通过苹果支付%s钱成功' % (self.name, money)))
# 归一化设计
def pay(name,price,kind):
class_name = getattr(sys.moudles[__name__],'kind') # 通过反射得到类的名字
obj = class_name(name)
obj.pay(price)
pay('alex',200,'Wechat')
pay('alex',200,'Apple')
########## 另一种方式:约束力强,依赖abc模块
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money): pass
'''只要你见到了项目中有这种类,你要知道你的子类中必须实现和pay同名的方法'''
7.8 反射
-
概念 : 根据字符串的形式去某个对象中操作他的成员
-
getattr(对象,'字符串') 根据字符串的形式去某个对象中获取对象的成员
-
获取类中的属性
class Foo(object): def __init__(self,name): self.name = name def func(self): print(123) obj = Foo('alex') # 获取变量 v1 = getattr(obj,'name') print(v1) # alex getattr(obj,'func')() # 123
-
获取当前py文件中的属性
import sys def func(): print(123) name = 'alex' getattr(sys.modules[__name__],'func') # 123 print(getattr(sys.modules[__name__]),'name') # alex
-
引用模块中的任意的变量
# a.py 中的属性有: def func(): print('in func') name = 'alex' class User: pass obj = User() # 运行脚本的文件 import a getattr(a,'func')() # in func getattr(a,'obj') # 得到地址 print(getattr(a,'name')) # alex
-
-
hasattr(对象,'字符串') 根据字符串的形式去某个对象中判断是否有该成员
class A: job = 'IT' def __init__(self): self.name = 'alex' self.age = 83 def func(self): print('in func') a = A() print(hasattr(a,'sex')) # False print(hasattr(a,'func')) # True if hasattr(a,'func'): if callable(getattr(a,'func')): # 判断这个函数是否可被调用 getattr(a,'func')() # in func
-
setattr(对象,"变量","值") 根据字符串的形式去某个对象中设置成员
class Foo: pass obj = Foo() obj.k1 = 999 setattr(obj,'k1',123) # obj.k1 = 123 print(obj.k1) # 123
-
delattr(对象,"变量") 根据字符串的形式去某个对象中删除成员
class Foo: pass obj = Foo() obj.k1 = 999 delattr(obj,'k1') print(obj.k1)
-
常用操作
class User: lis = [('登入','login'), ('注册','register'), ('删除文件','remove'), ('复制文件','copy')] def login(self): print('in login') def register(self): print('in register') def remove(self): print('in remove') def copy(self): print('in copy') obj = User() for index,item in enumerate(obj.lis,1): print(index,item[0]) while True: num = input('请选择要操作的序号:') if num.isdecimal() and 0 < int(num) <= len(obj.lis): if hasattr(obj,obj.lis[int(num)-1][1]): getattr(obj,obj.lis[int(num)-1][1])() else: print('输入有误')
7.9 模块: importlib
# from utils import redis
import importlib
middleware_classes = [
'utils.redis.Redis',
# 'utils.mysql.MySQL',
'utils.mongo.Mongo'
]
for path in middleware_classes:
module_path,class_name = path.rsplit('.',maxsplit=1)
module_object = importlib.import_module(module_path)# from utils import redis
cls = getattr(module_object,class_name)
obj = cls()
obj.connect()
# # 用字符串的形式导入模块。
# redis = importlib.import_module('utils.redis')
#
# # 用字符串的形式去对象(模块)找到他的成员。
# getattr(redis,'func')()
7.9.1 字符串格式化
-
几种表达形式
mes = '我是%s,年龄%s' %('Alex',99,) mes = '我是%(n1)s,年龄%(n2)s' %('n1':'Alex','n2':99) # v1 = "我是{0},年龄{1}".format('alex',19) v1 = "我是{0},年龄{1}".format(*('alex',19,)) print(v1) # v2 = "我是{name},年龄{age}".format(name='alex',age=18) v2 = "我是{name},年龄{age}".format(**{'name':'alex','age':18}) print(v2)
7.9.2 有序字典
from collections import orderedDict #导入模块将其转换为有序字典
info = OrderDict()
info['k1'] = 123
info['k2'] = 456
print(info.keys())
print(info.values())
print(info.items())
7.9.3 栈和队列
- 继承实现栈和队列
class Foo:
def __init__(self):
self.l = []
def put(self,num):
self.l.append(num)
return self.l
class Queue(Foo): # 队列: 先进先出
def get(self):
return self.l.pop(0)
class Stack(Foo): # 栈: 后进先出
def get(self):
return self.l.pop()
7.9.2 单例模式
-
无论实例化多少次,永远用的都是第一次实例化出对象
-
单例模式标准
#方法一 class Singleton: def __new__(cls,*args,**kwargs): if not hasattr(cls,'__instance'): cls.__instance = object.__new__(cls) return cls.__instance one = Singleton() two = Singleton() # 两者的内存地址完全一样 #方法二 class Baby: __instance = None def __new__(cls, *args, **kwargs): if cls.__instance is None: cls.__instance = super().__new__(cls) return cls.__instance def __init__(self,cloth,pants): self.cloth = cloth self.pants = pants b1 = Baby('红毛衣','绿皮裤') print(b1.cloth) b2 = Baby('白衬衫','黑豹纹') print(b1.cloth) print(b2.cloth)
7.9.3 日志 (模块logging)
-
日志处理本质; Logger / FileHandler / Formatter
-
日志的作用:
- 用来记录用户的行为--> 数据分析
- 用来记录用户的行为--> 操作审计
- 排查代码的错误
-
输出内容是有等级的: 默认处理warning级别及其以上的所有信息
logging.debug('debug message') # 调试 logging.info('info message') # 信息 logging.warning('warning message') # 警告 logging.error('error message') # 错误 logging.critical('critical message') # 批判性的 ''' 无论希望日志打印那些内容,都是自己写的,没有自动生成日志这种事 '''
-
将日志输出到屏幕
logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S ', ) logging.warning('warning message test2') logging.error('error message test2') logging.critical('critical message test2')
-
输出到文件,并且设置信息的等级,写入文件会出现乱码问题
logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', filename='tmp.log', # 将日志文件写入到名为tmp.log的文件中,以append的方式追加进去 level= logging.DEBUG # 设置最低处理等级为DEBUG,等级必须大写 ) logging.debug('debug 信息错误 test2') logging.info('warning 信息错误 test2') logging.warning('warning message test2') logging.error('error message test2') logging.critical('critical message test2')
-
同时向文件和屏幕上输出,并解决乱码问题 (常用这种方式处理日志)
fh = logging.FileHandler('tmp.log',encoding='utf-8') # 向文件输出并处理乱码问题 # fh2 = logging.FileHandler('tmp2.log',encoding='utf-8') # 也可同时输出到两个文件 sh = logging.StreamHandler() # 输出到屏幕 logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level= logging.DEBUG, # 设置最低处理等级为DEBUG,等级必须大写 # handlers=[fh,sh,fh2] handlers=[fh,sh] # 将需要输出到的内容添加到handlers ) logging.debug('debug 信息错误 test2') logging.info('warning 信息错误 test2') logging.warning('warning message test2') logging.error('error message test2') logging.critical('critical message test2')
-
做日志的切分
import time from logging import handlers sh = logging.StreamHandler() rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024,backupCount=5) # 按照大小做切割 fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8') logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s[line :%(lineno)d]-%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level= logging.DEBUG, handlers=[fh,rh,sh] ) for i in range(1,10): time.sleep(1) logging.error('KeyboardInterrupt error %s'%str(i))