计算机的硬件由:CPU /内存 /主板 /硬盘 /显卡等组成java
内存:python
优势:存取速度快mysql
缺点:断电后数据所有丢失linux
硬盘:c++
优势:断电后数据也会永久保存git
缺点:存取速度远远慢于内存程序员
操做系统用于协同或控制硬件之间进行工做面试
编程语言的开发者写的一个工具,将用户写的代码转换成二进制交给操做系统去执行redis
对于计算机而言,不管文件储存 / 网络传输等本质上都是二进制.微信/QQ等发的信息,图片,视频都是二进制算法
进制:
2进制: 计算机内部
8进制
10进制:人使用计算机通常都是10进制,计算机内部会将其转换成二进制
16进制:通常用于表示(用更短的内容表示更多的东西.通常是: \x 开头
ASCII :8位表示一个东西,只能识别英文
Unicode(万国码): 一个中文或字母等于四个字节,最多32位表示,内存进行数据计算时使用
utf-8:给万国码压缩,一个中文等于3个字节,一个英文一个字节,通常网络传输和文件存储时使用此编码
gbk : 一个中文两个字节
gb2312
注意:文件以什么方式保存就要以什么方式打开
py2默认解释器编码:ASCII
py3默认解释器编码:utf-8
如想修改默认编码,则可使用:
# -*- coding:utf-8 -*-
为何要有变量?
为某个值建立一个“外号”,之后在使用时候经过此外号就能够直接调用。
输出:
py2: print '你好' py3: print('你好')
输入 : 获得的内容永远是字符串
py2 raw_input("xxx") py3 input('xxx')
#示例 user_name = input("请输入你的姓名:") password = input("请输入你的密码:") content = "你的用户名是:" + user_name + "; 你的密码是:" + password print(content)
# 单行注释 ''' 多行注释 '''
# :示例:让用户输入一个数字,猜:若是数字 > 50,则输出:大了; 若是数字 <= 50 ,则输出:小了。 num = input('请输入一个数字') number = int(num) if number > 50: print('大了') else: print('小了')
while 循环
while 条件表达式: 循环体 # 当条件表达式的返回值为真时,则执行循环体中的语句,执行完毕后,从新判断条件表达式的返回值,直到表达式的返回的结果为假时,退出循环.
for 循环
for 某个变量 in 要循环的对象: 循环体 # 其中某个变量是用于保存读取出的值,对象为要遍历或迭代的对象,能够是任何有序的序列对象,如字符串.列表.元组等.循环体为一组被重复执行的语句
死循环考虑while, 有限循环优先考虑for循环
break 语句
意思为结束当前循环
continue 语句
意思:当循环遇到continue时,再也不继续往下走,而是回到当前循环
%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)
算数运算
示例: 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
表示空(无任何功能,专门用于提供空值)
py2:整型除法只能保留整数位。
from __future__ import division v = 9 /2 print(v) #保留所有值
py3
只有两个结果:True/False: 0/''/[]/()/{}/set() 转布尔时为False,其他结果都为Ture
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: 去除空白,也能够去除换行符(\n)和指定字符串
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() 判断字符串只有字母组成
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
格式
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'}
交集 (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}
注意
#嵌套时 列表/字典/集合 不能做为集合里面的元素
len(计算长度) 均可以
索引 集合是无序的因此没有,其他都有
切片 字典和集合没有,其他都有
步长 字典和集合没有,其他都有 " 经过步长能够反转字符串:[ : : -1 ]"
for 循环 均可以
删除 字符串 / 元组 是不可变类型,因此不能删除,其他都有
修改 字符串 / 元组 是不可变类型,因此不能删除,其他都有
读取: 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()
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()
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() # 缩进中的代码执行完毕后,自动关闭文件
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)
v = 前面 if 条件 else 后面 if 条件: v = '前面' else: v = '后面'
目前:面向过程编程 [可读性差/可重复性差]
函数式编程
函数的基本结构
#函数的定义 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('写入失败')
位置参数 : (调用函数并传入函数)
关键字传参:
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
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)
函数名当作变量来使用:
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
用于表示简单的函数
注意:列表全部方法的返回值基本都为none,字符串全部方法的返回值基本都返回新值
其余:
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取值的内置函数
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)
函数能够做为返回值
面试题相关:
闭包
什么是闭包:
递归 :
#递归打印斐波那契数 def func(a,b): # 1 # 1 # 2 # 3 # 5 print(b) func(b,a+b) func(0,1)
装饰器编写的格式
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)
列表推导式(也叫列表生成式)
用一行代码构建一个比较复杂有规律的列表
基本格式
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)) # 生成器推导式(非元组推导式),建立了一个生成器,内部循环为执行。
__init__
.py文件内置模块
第三方模块 :
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
什么是模块
什么是包
__init__
.py文件中的内容示例: # 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()
导入一个包(文件夹)至关于执行了这个包下的__init__
文件,并不至关于把这个包下的全部文件都导入进来了
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之间的浮点数
做用: ,密文登入验证 / 检验文件的一致性
用于加密相关的操做,把一个大的数据切分红不一样块,分别对不一样的块进行加密汇总的结果,和直接对总体数据加密的结果是一致的
将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('输入正确')
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打印
\n 换行
\t 制表符
\r 回到当前行的起始位置
print('1231你好你好你好23\r',end='') print('你好',end='') #因为\r的存在,回到了当前行的起始位置,没有换行,只会打印'你好'
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 查看导入了那些模块
os.path.exists(path) , 若是path存在,返回True;若是path不存在,返回False
os.path.getsize() 获取文件的大小
a = os.path.getsize(r'D:\python全栈\网络编程\day28\one\server.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 \n.txt result = os.path.join(path,'n1','n2','n3') print(result) #C:\python36\新建文件夹\python36.exe \n1\n2\n3
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全栈\网络编程\day28\four') print(a) # 结果为: four a = os.path.basename('D:\python全栈\网络编程\day28\four/') print(a) # 结果:啥都没有,空
v1 = r"D:\code\s21day14\n1.mp4" (推荐) print(v1) # D:\code\s21day14\n1.mp4 v2 = "D:\\code\\s21day14\\n1.mp4" (不推荐) print(v2) # D:\code\s21day14\n1.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%%\r' %val ,end='')
删除
# 删除文件 os.remove('文件名') # 删除目录(必须是空目录) os.removedirs('目录名')
os.getcwd 查看工做目录
os.chdir 改变工做目录
os.urandom(16) 获取一个随机的16字节大小的字符串
# 和执行操做系统命令相关 os.popen/os.system import os os.system('dir') ret = os.popen('dir') print(ret.read())
序列化:将内存中的数据转换成字符串,用以保存文件或经过网络传输
反序列化:从文件或网络中获取的数据转换成内存中原来的数据类型
json : 一个特殊的字符串 [长得像列表/字典/字符串/数字/真假]
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类型的结果写到文件中 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]) + '\n') f.write(json.dumps([4,5,5]) + '\n') # 把分次序列化的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'\x80\x03]q\x00(K\x01K\x02K\x03e.' l2 = pickle.loads(st) print(l2,type(l2)) # [1, 2, 3] <class 'list'>
dump load 直接写入文件(还能够写入函数名,对象)
删除目录
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:\code\xxxxxx\xxxx',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:\code\s21day16\lizhongwei') #压缩文件 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))
time :
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
import requests # 获取网页源码 ret = requests.get('一个网址 ').strip() # 输入网址后加一个空格 print(ret.content) # 以字节的方式去显示,中文显示为字符 print(ret.text) # 以文本的方式去显示
示例: #写函数去,接受一个列表。列表中都是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'])
__next__
方法且每次调用都获取可迭代对象中的元素__iter__
()__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__
方法且返回一个迭代器生成器 (函数的变异)
获取生成器的三种方式
生成器的本质就是迭代器,
生成器函数 (内部是否包含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)) #获得的是一个列表
总结:
__init__
,把空间的内存地址做为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)
# 父类(基类) class Base: def f1(self): pass # 子类(派生类) class Foo(Base): def f2(self): pass # 建立一个子类的对象 obj = Foo() # 执行对象.方法时,优先在本身的类中找,若是没有就是父类中找。 obj.f2() obj.f1() # 建立了一个父类的对象 obj = Base() obj.f1()
继承方法中的查找方法的顺序
父类和子类方法的选择
继承的其余现象
![]() |
---|
![]() |
多态:一个类表现出的多种形态,其实是经过继承来完成的
''' 若是狗类继承动物类,猫类也继承动物类 那么猫的对象也是动物类型的,狗的对象也是动物类型的 在这个例子中,动物这个类型表现出了猫和狗的形态 '''
# Python def func(arg): v = arg[-1] # arg.append(9) print(v)
广义:把属性的方法封装起来,外面就不能直接调用了,要经过类的名字来调用
狭义: 把属性和方法藏起来,外面不能调用,只能在内部偷偷调用
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'
私有的内容不能被子类使用
其余语言中的数据级别:
实例(对象)
类
类变量
####应用示例##### 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)
静态方法
定义
执行
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() # 不推荐
类方法
定义:
执行:
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作装饰器且参数无限制 调用: 类.方法()直接调用 对象.方法()也可调用 (不推荐) '''
属性
定义:
执行:
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 ,继承深度优先 '''
__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__
__str__
方法__str__
,就调用 __repr__
方法__repr__
不只仅是 __str__
的替代品,还有本身的功能__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)) # ['大壮']
__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__方法
特殊成员:就是为了能快速实现执行某些方法而生
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__)
基本格式
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)
表象:能够被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方法
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同名的方法'''
概念 : 根据字符串的形式去某个对象中操做他的成员
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('输入有误')
# 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')()
几种表达形式
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)
from collections import orderedDict #导入模块将其转换为有序字典 info = OrderDict() info['k1'] = 123 info['k2'] = 456 print(info.keys()) print(info.values()) print(info.items())
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()
不管实例化多少次,永远用的都是第一次实例化出对象
单例模式标准
#方法一 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)
日志处理本质; 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))