一、装饰器【重点】
- 装饰器定义:在代码运行期间,在不修改原函数的基础上,可以动态增加函数功能的方式,被称为装饰器(Decorator)。
- 优点:在团队开发中,如果两个或者两个以上的程序员会用到相同的功能,但是功能又有细微的差别,采用装饰器:相互不影响,代码简化。
1.1 创建装饰器
-
语法:
def outer(fun): def inner(): fun() return inner outer(fun)
1.2 装饰器的使用
1.2.1 简单装饰器
-
outer外部函数就被称为装饰器!
1.简单的装饰器 def test(): print("拼搏到无能为力,坚持到感动自己") a.书写闭包 b.给外部函数设置参数,fun表示的是原函数 def outer(fun): def inner(): d.给原函数增加功能 print("hello") c.调用原函数 fun() return inner e.使用闭包 f = outer(test) #f = inner f() #inner()
1.2.2 有参数的装饰器
-
当原函数有参数,装饰器的作用是为了操作原函数中的参数,给inner设置参数。
def wrapper(fun): def inner(num): #增加新功能:过滤负数 if num < 0: num = 0 #调用原函数 fun(num) #age = num return inner #将wrapper装饰器应用在了getAge函数上, # @wrapper # 等价于:getAge= wrapper(getAge) def getAge(age): print(age) getAge(10) getAge(-5)
1.2.3 不定长参数的装饰器
-
当同一个装饰器作用于不同函数的时候,这些函数的参数的个数是不相同的。
def wrapper(fun): def inner(*args): print("hello") fun(*args) #a = args[0] b = args[1] return inner @wrapper def fun1(a,b): print(a + b) ---> 30 @wrapper def fun2(a,b,c,d): print(a,b,c,d) ---> 1 2 3 4 fun1(10,20) fun2(1,2,3,4)
-
通用装饰器
def outer(fn): def inner(*args,**kwargs): print("before") res = fn(*args,**kwargs) print("after") return res return inner @outer def eat(): print("吃饭") @outer def sing(song): print("哈哈唱:", song) return "一般" eat() res = sing("大碗宽面") print(res)
1.2.4 多个装饰器作用于同一个函数
-
多个装饰器作用于同一个函数的时候,从第一个装饰器开始,从上往下依次执行,但是,原函数只会被执行一次。
def outer(f): def inner(): print("before") f() print("after") return inner def outer1(f): def inner(): print("befor1") f() print("aftor1") return inner @outer @outer1 def sing(): print("唱歌") sing() 结果: before befor1 唱歌 aftor1 after
1.3 总结
- 增加的功能可以写在原函数调用的前面或者后面;
- 当原函数有参数,装饰器的作用是为了操作原函数中的参数,给inner设置参数;
- 当使用@简化时,在同一个文件中,装饰器必须出现的原函数的前面;
- 多个装饰器作用于同一个函数的时候,从第一个装饰器开始,从上往下依次执行,原函数只会被执行一次。
二、函数递归【重点】
-
递归函数定义:一个会调用自身的函数(在一个函数的内部,自己调用自己)。
-
递归调用:递归中包含了一种隐式的循环,他会重复指定某段代码(函数体),但这种循环不需要条件控制。
-
解决思路:
1、找公式,如:fn(n)=n*fn(n-1)
2、找到相邻两次循环之间的关系
3、找临界值,如:n=1,f(1)=1
4、一定要相信函数能实现。 -
优点:简化代码,逻辑清晰。
-
注意:以后在实际项目中尽量少用递归,如果隐式循环的次数太多,会导致内存泄漏(栈溢出)。
2.1 案例
-
案例一:求第n个斐波那契数
---------------------1 2 3 4 5 6 7 8 9 10 11.。。。
斐波那契数列:1,1,2,3,5,8,13,21,34,55,89…解决问题:报一个数,输出数列中对应的数
规律:
a.第一个位置和第二个位置上数是固定的,都是1
b.第n个位置上的数:第 n - 1 的数 + 第 n - 2 的数r1 = func1(1) ------>1
r2 = func1(2) ------>1
r3 = fun1(3) ------>func1(1) + func1(2)----->1 + 1 = 2
r4 = fun1(4)------->fun1(3) + fun1(2) ----->func1(1) + func1(2) + fun1(2) ---->1 + 1 + 1 = 3
r5 = fun1(5) ----->fun1(4) + fun1(3) ----->fun1(3) + fun1(2) + func1(1) + func1(2)—>func1(1) + func1(2) ++ fun1(2) + func1(1) + func1(2)—>5
…
rn = fun1(n) ----->fun1(n- 1) + fun1(n - 2)
“”"def func1(num): #临界值 if num == 1 or num == 2: return 1 else: #print("~~~~",num) result = func1(num- 1) + func1(num - 2) #result = func1(1) + func1(2) --->1 + 1 =2 return result print(func1(10))
-
案例二:使用递归计算1~某个数之间的和
“”"
add(1) = 1 :临界值
add(2) = add(1) + 2
add(3) = add(2) + 3 ---->add(1) + 2 + 3 = 1 + 2 + 3
add(4) = add(3) + 4---->add(2) + 3 + 4 ---->add(1) + 2 + 3 + 4---->1 + 2 + 3 + 4
…
add(n) = add(n - 1) + n
“”"def add(num): if num == 1: return 1 else: return add(num - 1) + num print(add(100))
三、栈和队列【了解】
用于存储数据的线性表
栈:在表的一端进行插入和删除
队列:在表的一端进行插入,在表的另一端进行数据的删除
3.1 栈(Stack)
-
栈:一种数据结构。开口向上的容器:先进后出,后进先出。用列表实现栈。
stack = [] # 入栈 stack.append('a') print(stack) stack.append('b') print(stack) stack.append('c') print(stack) stack.append('d') print(stack) # 出栈 stack.pop() print(stack) stack.pop() print(stack) stack.pop() print(stack) stack.pop() print(stack)
3.2 队列(queue)
-
队列:水平放置的水管,先进先出,后进后出。
-
队列格式:deque([1, 2, 3, 4])
队列必须先调用collections:import collections。再用collections创建队列。
#队列 # from collections import deque import collections #创建队列 queue = collections.deque() print(queue) # 入队列 queue.append('a') print(queue) queue.append('b') print(queue) queue.append('c') print(queue) queue.append('d') print(queue) # 出序列 queue.popleft() # 从左边删 print(queue) queue.popleft() print(queue) queue.popleft() print(queue) queue.popleft() print(queue)