装饰器
学习思路:
a、如何定义装饰器
b、装饰器的工作原理【系统的装饰器】
a、如何定义装饰器
"""
装饰器的本质:就是一个闭包,只不过改闭包的外部函数的参数为另一个函数【需要被装饰的函数】
在装饰器的使用过程中,应用到了函数的本质
装饰器的好处:可以在不用修改原函数的基础上,给指定的函数增加新的功能
"""
一个最简单的装饰器
def now():
print("为了部落")
def wrapper(fun):
print("外部函数用了哦")
def inner():
# 在inner中,调用原函数,增加新功能,顺序可以根据需求进行修改
fun()
print("新的功能")
return inner
print()
"""
wrapper被称为装饰器的名称
应用场景:统计函数的执行时间,日志处理,函数执行完毕的清理功能,权限校验,缓存的处理
"""
def test():
for i in range(10):
print()
def outter(fun1):
def inner():
fun1()
'''
for i in range(1,10):
for j in range(1,i+1):
print("%dx%d=%d"%(j,i,j*i),end=' ')
print()
return inner
f = outter(test)
f()
b、装饰器的工作原理
#有参数的装饰器 注意:使用 @装饰器名 作用于原函数,则装饰器必须先存在,才能修饰函数
def wrapper(f):
def inner(age):
if age < 0:
age = -age
#调用原函数
f(age)
return inner
@wrapper
def get_age(age):
print("你的年龄是:%d"% age)
"""
# 一个装饰器作用于多个函数
# 多个不同的函数增加了同一个功能
"""
def wrapper(fun):
def inner(*args, **kwargs):
fun(*args, **kwargs)
print("new")
return inner
@wrapper
def func1():
print("func~~~~111")
func1() # func~~~~111 new
@wrapper
def func2(a):
print("func~~~~222")
func2(0) # func~~~~222 new
@wrapper
def func3(num1, num2, num3):
print("func~~~~~333")
func3(10, 20, 30) # func~~~~~333 new
"""
多个装饰器作用于同一个函数
# 给一个函数同时增加多个不同的功能
"""
#例1
def wrapper1(func1):
def inner1():
print("装饰器~~~111")
func1()
return inner1
def wrapper2(func2):
def inner2():
print("装饰器~~~~222")
func2()
return inner2
def wrapper3(func3):
def inner3():
print("装饰器~~~333")
func3()
return inner3
@wrapper1 # 第三步: func1 = show[show------inner2] show = inner1
@wrapper2 # 第二步: func2 = show[show--->inner3] show = inner2
@wrapper3 # 传参过程: 第一步: func3 = show show = inner3
def show():
print("showing")
show()
"""
装饰器~~~111
装饰器~~~~222
装饰器~~~333
showing
"""
# 例2
def wrapper_1(func1):
def inner1():
print("装饰器~~~1111")
func1()
return inner1
def wrapper_2(func2):
def inner2():
print("装饰器~~~2222")
func2()
return inner2
def wrapper_3(func3):
def inner3():
print("装饰器~~~3333")
func3()
return inner3
@wrapper_1
@wrapper_3
@wrapper_2
def show():
print("showing")
show()
"""
装饰器~~~1111
装饰器~~~3333
装饰器~~~2222
showing
"""
print("*" * 30)
"""
"""
a、当多个装饰器修饰同一个函数的时候,采用的就近原则,从上往下进行传参【一直改变原函数的指向】,从上往下执行
b、原函数都只会被执行一次
c、通过不断修改原函数的指向完成整个装饰器的调用过程
"""
def wrapper_1(func1):
def inner1():
print("装饰器~~~1111")
func1()
return inner1
def wrapper_2(func2):
def inner2():
func2()
print("装饰器~~~2222")
return inner2
def wrapper_3(func3):
def inner3():
print("装饰器~~~3333")
func3()
return inner3
@wrapper_1 #func1 = show[show---->inner2] show = inner1
@wrapper_2 #func2 = show[show---->inner3] show = inner2
@wrapper_3 #func3=show show = inner3
def show():
print("showing")
show()
"""
装饰器~~~1111
装饰器~~~3333
showing
装饰器~~~2222
def wrapper_1(func1):
def inner1():
func1()
print("装饰器~~~1111")
return inner1
def wrapper_2(func2):
def inner2():
func2()
print("装饰器~~~2222")
return inner2
def wrapper_3(func3):
def inner3():
print("装饰器~~~3333")
func3()
return inner3
@wrapper_1
@wrapper_3
@wrapper_2
def show():
print("showing")
show()
"""
装饰器~~~3333
showing
装饰器~~~2222
装饰器~~~1111
"""
"""
总结:
a。当多个装饰器修饰同一个函数时,采用的就近原则,从下往上进行传参【一直改变原函数的指向】,从上往下执行
b.原函数都只会被执行一次
c.通过不断修改原函数的指向完成整个装饰器的调用过程
"""
高阶函数
一个函数的参数为另外一个函数,返回一个结果,该函数被称为高阶函数
1、map映射
#map的用法
"""
map(fn,Iterable1,Iterable2.....)
fn:函数【def 和 lambda】
Iterable:可迭代对象
功能:根据fn中的逻辑,依次作用域序列中的每一个元素,最终返回一个新的序列
"""
# 1、
list1 = [1,2,3,4,5]
result = map(str,list1)
print(list(result))
def add(x,y):
return x + y
result1 = map(add,[1,2,3],[4,5,6])
print(list(result1))
'''
注意:
1、map中的序列有几个,函数的参数一般设置几个【一一对应】
2、map中的函数一般要设置返回值,否则生成的元素全部是None【将结果保存在一个新容器中】
3、多个序列的长度可以不一致,以元素少的序列作为参照
'''
# 练习:
list1 = ["faf","Hello","AAA"]
newlist1 = [ch.upper() for ch in list1]
print(newlist1)
result = list(map(lambda ch:ch.upper(),list1))
print(result)
from functools import reduce
"""
reduce(fn,Iterable)
功能:使用fn首先将Iterable中的第0个和第一个元素进行运算,将得到的结果和第2个元素进行运算
知道Iterable中的元素全部参与运算
举例:
"""
# 需求:求一个列表中国所有元素的和
list1 = [1,2,3,4,5]
# 方式一
total = 0
for num in list1:
total += num
print(total)
# 方式二:
def add(a, b):
return a + b
result = reduce(add, list1)
print(result)
# 练习3:将[2,4,6,8]转换成整数2468
def ssr(x,y):
return str(x) + str(y)
result1 = reduce(ssr, [2,4,6,8])
print(int(result1), type(result1))
# 1
def check(x,y):
return x * 10 + y
# 2
result2 = reduce(check, [2, 4, 6, 8])
print(result2)
# 3
result3 = reduce(lambda x, y: x * 10 + y, [2, 4, 6, 8])
print(result3)
# 4、需求:使用map和reduce实现字符串转整型的操作
# "6523" ---------> 6523
# 建立映射关系
def str_to_int(s):
dict1 = {'0': 0, "1": 1, "2": 2, '3': 3}
return dict1[s]
result22 = list(map(str_to_int, '3231'))
print(result22)
# 实现转换
result33 = reduce(lambda x, y:x * y +y, result22)
print(result33)
# 合起来写
result44 = reduce(lambda x, y:x *10+y,map(str_to_int,'3231'))
print(result44)
2、reduce
from functools import reduce
"""
reduce(fn,Iterable)
功能:使用fn首先将Iterable中的第0个和第一个元素进行运算,将得到的结果和第2个元素进行运算
知道Iterable中的元素全部参与运算
举例:
func(x,y)
[a,b,c,d]
reduce(func((a,b)c,d))
工作原理:
func(func(func(a,b),c),d)
"""
# 需求:求一个列表中国所有元素的和
list1 = [1,2,3,4,5]
# 方式一
total = 0
for num in list1:
total += num
print(total)
# 方式二:
def add(a, b):
return a + b
result = reduce(add, list1)
print(result)
# 练习3:将[2,4,6,8]转换成整数2468
def ssr(x,y):
return str(x) + str(y)
result1 = reduce(ssr, [2,4,6,8])
print(int(result1), type(result1))
# 1
def check(x,y):
return x * 10 + y
# 2
result2 = reduce(check, [2, 4, 6, 8])
print(result2)
# 3
result3 = reduce(lambda x, y: x * 10 + y, [2, 4, 6, 8])
print(result3)
# 4、需求:使用map和reduce实现字符串转整型的操作
# "6523" ---------> 6523
# 建立映射关系
def str_to_int(s):
dict1 = {'0': 0, "1": 1, "2": 2, '3': 3}
return dict1[s]
result22 = list(map(str_to_int, '3231'))
print(result22)
# 实现转换
result33 = reduce(lambda x, y:x * y +y, result22)
print(result33)
# 合起来写
result44 = reduce(lambda x, y:x *10+y,map(str_to_int,'3231'))
print(result44)
3、filter过滤
"""
filter(fn,Iterable)
功能:通过条件过滤可迭代对象
根据函数的返回值为True或者false决定是否保留元素,True保存,F过滤
"""
# 1、过滤奇数
list1 = [1,2,3,4,5,6,7,8,9,10]
def check(num):
if num % 2 ==0:
return True
else:
return False
result1 = filter(check,list1)
print(list(result1))
# 2、需求,将其中为"无"的数据过滤掉
list2 = [["张三", 18, 100,'跳舞'], ["狗蛋儿", 15, 95,"无"], ["jack", 19, 60, "唱歌"]]
def test(ch):
if ch == "无":
return False
return True
newlist = []
for sublist in list2:
m = filter(test,sublist)
newlist.append(list(m))
print(newlist)
4、sorted排序
# 一、sort
list1 = [3,534,54,654,28]
list_1 = ['ss','sasadasd','dsaftdsffas''sdfs']
# 升序
list1.sort()
print(list1) # [3, 28, 54, 534, 654]
# 降序
list1.sort(reverse=True)
print(list1) # [654, 534, 54, 28, 3]
# 自定义排序
list_1.sort(key=len)
print(list_1) # ['ss', 'sasadasd', 'dsaftdsffassdfs']
# 二、sorted
list1 = [3,534,54,654,28]
list_1 = ['ss','sasadasd','dsaftdsffas''sdfs']
list2 = sorted(list1)
print(list1) # [3, 534, 54, 654, 28]
print(list2) # [3, 28, 54, 534, 654]
list3 = sorted(list1,reverse=True)
print(list1) # [3, 534, 54, 654, 28]
print(list3) # [654, 534, 54, 28, 3]
list4 = sorted(list_1,key=len,reverse=True)
print(list4) # ['dsaftdsffassdfs', 'sasadasd', 'ss']
递归函数
1、概念
a、递归函数:一个函数调用自身,该函数被称为递归函数
b、递归调用:整个代码执行的过程被称为递归调用
c、递归包含了一种隐式的循环,它就会重复某段代码,但是这种循环不需要条件进行控制
d、需要解决的问题:再合适的实际让隐式的循环停止下来
e、使用递归解决问题的思路:
1、找到一个临界值【能让递归停止下来】
2、找到两次循环的关系
# 斐波那契数列
"""
1 2 3 4 5 6 7 8 9 10 11 12 13……
1 1 2 3 5 8 13 21 34 55 89 144……
规律:
a、第一个位置和第二个位置上的数是固定的,都是1------->临界值【条件】
b、第n个位置上的数 = (n-1) + (n-2)
分析:
func(3) = func(2) + func(1) ------>1 + 1 = 2
func(5) = func(4) + fun(3)
= func(3) + func(2) +func(2) + func(1)
= func(2)+func(1)+ func(2) + func(2) +fun(1)
"""
count = 0
def func(n):
global count
count += 1
if n == 1 or n == 2:
return 1
else:
return func(n-1) + func(n-2)
print(func(10)) # 55
print('执行的次数:',count) # 109
# 注意:递归中必须要有返回值,因为下一次运算中,一般要用到上一次的结果
# 练习:使用递归求1~某个数之间所有整数的和:
def get_total(num):
if num == 1:
return 1
else:
return get_total(num - 1) + num
print(get_total(100)) # 5050
"""
分析:
gettotal(10) = gettotal(9) + 10
get....9 = get.....8 + 9
....
gettotal(1) = 1 -------临界值
"""
"""
总结:
优点:代码实现简单
缺点:过深的递归可能会造成栈溢出
建议:没事少装逼,慎用
"""
栈和队列
【面试题:栈和队列的区别和联系】
栈:Stack,是限定在表的一端进行插入和删除操作的线性表【抽象成一个开口向上的容器】
队列:Queue,是限定在表的一端进行插入操作,在表的另外一端进行删除操作的线性表【抽象成一个水平放置的水管】
线性表:属于一种线性结构【容器】,可以包含有限的序列节点,其中插入数据和删除数据都有一定的规律
相同点:
a.都是线性表
b.二者的插入操作都是表尾进行的
c.二者都可以通过顺序结构和链式结构实现
d.二者在实现插入和删除操作时,时间复杂度和空间复杂度是相同的【工作效率相同】
不同点:
a.删除的位置不同:栈的删除在表尾进行,队列的删除在表头进行
b.使用场景不同:
栈:Python中的基本语法【表达式的求值和转换,函数的定义和调用】
队列:计算机中各种资源的分配【系统】
c.工作原理不同:
栈:先进后出,后进先出
队列:先进先出,后进后出
栈
stack = []
print(stack)
#入栈【向栈中添加数据】:append
stack.append(11)
print(stack)
stack.append(22)
print(stack)
stack.append(33)
print(stack)
stack.append(44)
print(stack)
#出栈【从栈中删除数据】:pop
stack.pop()
print(stack)
stack.pop()
print(stack)
stack.pop()
print(stack)
stack.pop()
print(stack)
队列
from collections import deque
queue = deque()
print(queue)
#入队【向队列中添加数据】:append
queue.append(11)
print(queue)
queue.append(22)
print(queue)
queue.append(33)
print(queue)
queue.append(44)
print(queue)
#出队【从队列中删除数据】;popleft/pop
queue.popleft()
print(queue)
queue.popleft()
print(queue)
queue.popleft()
print(queue)
queue.popleft()
print(queue)
遍历目录
import os
path = r"C:\Program Files (x86)"
# 1、listdir 列出指定目录下所有的内容【文件或者文件夹】,返回一个列表,列表中的元素为文件或者文件夹名称
list1 = os.listdir(path)
print(list1)
# 2、join根据父路径和当前文件夹的名称给拼接路径
path1 = path + "\\" + "Google"
print(path1)
path2 = os.path.join(path,"Google")
print(path2)
# 3、isfile/isdir: 判断指定的路径是否是文件或者文件夹
result = os.path.isfile(path2)
print(result)
result = os.path.isdir(path2)
print(result)
递归遍历目录
import os
def get_file(path):
if os.path.isfile(path):
print("文件",path)
return
# 说明path是一个文件夹
file_list = os.listdir(path)
# 遍历列表,凭借每个完整的路径
for file_name in file_list:
# 拼接
file_path = os.path.join(path,file_name)
if os.path.isdir(file_path):
print("目录",file_path)
# 使用递归
get_file(file_path)
else:
print("文件",file_path)
if __name__ == "__main__":
path = r"E:\eclipse_PHP"
get_file(path)
使用递归遍历目录
import os
# 使用栈遍历
# 思路:如果路径是目录,则添加到栈中,如果是文件,则直接打印
def get_file(path):
# 定义一个空栈
stack = []
if os.path.isfile(path):
print("文件:",path)
return
# 将path添加到栈中
stack.append(path)
# 处理栈,是一个循环过程,循环条件:栈不为空
while len(stack) != 0:
dir_path = stack.pop()
# 获取初始路径下的所有路径
file_list = os.listdir(dir_path)
# 遍历,拼接路径
for file_name in file_list:
file_path = os.path.join(dir_path,file_name)
if os.path.isdir(file_path):
# 如果是目录,则加到栈中
stack.append(file_path)
else:
print("文件:",file_path)
if __name__ == "__main__":
path = r"E:\eclipse_PHP"
get_file(path)
使用队列遍历目录
#使用队列遍历
import os
from collections import deque
import os
from collections import deque
# 使用栈遍历
# 思路:如果路径是目录,则添加到栈中,如果是文件,则直接打印
def get_file(path):
# 定义一个空栈
queue = deque()
if os.path.isfile(path):
print("文件:",path)
return
# 将path添加到栈中
queue.append(path)
# 处理栈,是一个循环过程,循环条件:栈不为空
while len(queue) != 0:
dir_path = queue.pop()
# 获取初始路径下的所有路径
file_list = os.listdir(dir_path)
# 遍历,拼接路径
for file_name in file_list:
file_path = os.path.join(dir_path,file_name)
if os.path.isdir(file_path):
# 如果是目录,则加到栈中
queue.append(file_path)
else:
print("文件:",file_path)
if __name__ == "__main__":
path = r"E:\eclipse_PHP"
get_file(path)