一、裝飾器【掌握】
1.案例
代碼演示:
def test():
print("拼搏到無能為力,堅持到感動自己")
f = test() #變量可以指向指向函數(shù),函數(shù)名也是一個變量,所以變量可以當做函數(shù)調(diào)用
f()
#思考問題:test增加功能,但是不能修改test函數(shù)內(nèi)部----->裝飾器
在代碼運行期間,可以動態(tài)增加函數(shù)功能的方式,被稱為裝飾器【Decorator】
也就是說,在不修改原函數(shù)的基礎(chǔ)上,給原函數(shù)增加功能
好處:在團隊開發(fā)中,如果兩個或者兩個以上的程序員會用到相同的功能,但是功能又有細微的差別,采用裝飾器:相互不影響,代碼簡化
2.使用
2.1簡單裝飾器
代碼演示:
#1.簡單的裝飾器
def test():
print("拼搏到無能為力,堅持到感動自己")
#a.書寫閉包
#b.給外部函數(shù)設(shè)置參數(shù),fun表示的是原函數(shù)
def outer(fun):
def inner():
# d.給原函數(shù)增加功能
print("hello")
#c.調(diào)用原函數(shù)
fun()
return inner
#e.使用閉包
f = outer(test) #f = inner
f() #inner()
#注意:增加的功能可以寫在原函數(shù)調(diào)用的前面或者后面
#注意:outer函數(shù)就被稱為裝飾器
#練習:給下面的函數(shù)添加功能,打印九九乘法表
def show():
for i in range(10):
print(i)
def outer1(fun):
def inner1():
fun()
for i in range(1,10):
for j in range(1,i + 1):
print("%dx%d=%d"%(j,i,i * j),end=" ")
print("")
return inner1
f1 = outer1(show)
f1()
2.2有參數(shù)的裝飾器
代碼演示:
#2.原函數(shù)有參數(shù)的裝飾器
def getAge(age):
print(age)
getAge(10)
getAge(-5)
print("************")
#需求:在不修改原函數(shù)的基礎(chǔ)上,進行數(shù)據(jù)的過濾:當用戶輸入age為負數(shù)的時候,則置為0
def wrapper(fun):
#注意:當原函數(shù)有參數(shù),裝飾器的作用是為了操作原函數(shù)中的參數(shù),給inner設(shè)置參數(shù)
def inner(num):
#增加新功能:過濾負數(shù)
if num < 0:
num = 0
#調(diào)用原函數(shù)
fun(num) #age = num
return inner
f = wrapper(getAge)
f(10) #num = 10
f(-5)
2.3系統(tǒng)的簡寫
代碼演示:
#3.簡化demo2中的操作:@裝飾器的名稱 應(yīng)用到原函數(shù)中
#需求:在不修改原函數(shù)的基礎(chǔ)上,進行數(shù)據(jù)的過濾:當用戶輸入age為負數(shù)的時候,則置為0
def wrapper(fun):
#注意:當原函數(shù)有參數(shù),裝飾器的作用是為了操作原函數(shù)中的參數(shù),給inner設(shè)置參數(shù)
def inner(num):
#增加新功能:過濾負數(shù)
if num < 0:
num = 0
#調(diào)用原函數(shù)
fun(num) #age = num
return inner
#將wrapper裝飾器應(yīng)用在了getAge函數(shù)上,
@wrapper
def getAge(age):
print(age)
getAge(10)
getAge(-5)
"""
@wrapper
等價于
f = wrapper(getAge)
f(10) #num = 10
#注意;當使用@的時候,在同一個文件中,裝飾器必須出現(xiàn)的原函數(shù)的前面
"""
2.4不定長參數(shù)的裝飾器
代碼演示:
#4.不定長參數(shù)的裝飾器
#應(yīng)用場景:當同一個裝飾器作用于不同函數(shù)的時候,這些函數(shù)的參數(shù)的個數(shù)是不相同的
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)
@wrapper
def fun2(a,b,c,d):
print(a,b,c,d)
fun1(10,20) #args = (10,20)
fun2(1,2,3,4)
2.5多個裝飾器作用于同一個函數(shù)
代碼演示:
#5.將多個裝飾器應(yīng)用到同一個函數(shù)上
def wrapper1(fun):
def inner1():
print("1~~~~")
fun()
return inner1
def wrapper2(fun):
def inner2():
print("2~~~~")
fun()
return inner2
@wrapper1
@wrapper2
def show():
print("hello")
show()
"""
1~~~~
2~~~~
hello
"""
#結(jié)論:多個裝飾器作用于同一個函數(shù)的時候,從第一個裝飾器開始,從上往下依次執(zhí)行,但是,原函數(shù)只會被執(zhí)行一次
二、函數(shù)遞歸【掌握】
1.概念
遞歸函數(shù):一個會調(diào)用自身的函數(shù)【在一個函數(shù)的內(nèi)部,自己調(diào)用自己】
遞歸調(diào)用
遞歸中包含了一種隱式的循環(huán),他會重復(fù)指定某段代碼【函數(shù)體】,但這種循環(huán)不需要條件控制
使用遞歸解決問題思路:
a.找到一個臨界條件【臨界值】
b.找到相鄰兩次循環(huán)之間的關(guān)系
c.一般情況下,會找到一個規(guī)律【公式】
2.使用
代碼演示:
#案例一
"""
1 2 3 4 5 6 7 8 9 10 11.。。。
斐波那契數(shù)列:1,1,2,3,5,8,13,21,34,55,89.....
解決問題:報一個數(shù),輸出數(shù)列中對應(yīng)的數(shù)
規(guī)律:
a.第一個位置和第二個位置上數(shù)是固定的,都是1
b.第n個位置上的數(shù):第 n - 1 的數(shù) + 第 n - 2 的數(shù)
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~某個數(shù)之間的和
"""
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):
"""
n = 1
sum = 0
while n <= 100:
sum += n
n += 1
return sum
sum1 = 0
for i in range(1,num + 1):
sum1 += i
return sum1
"""
#使用遞歸實現(xiàn)
if num == 1:
return 1
else:
return add(num - 1) + num
print(add(100))
注意:以后在實際項目中盡量少用遞歸,如果隱式循環(huán)的次數(shù)太多,會導(dǎo)致內(nèi)存泄漏【棧溢出】
優(yōu)點:簡化代碼,邏輯清晰
三、棧和隊列【了解】
用于存儲數(shù)據(jù)的線性表
棧:在表的一端進行插入和刪除
隊列:在表的一端進行插入,在表的另一端進行數(shù)據(jù)的刪除
1.棧
Stack
開口向上的容器:先進后出,后進先出
代碼演示:
#list的底層維護了一個棧的線性表
myStack = []
#插入數(shù)據(jù)
#數(shù)據(jù)入棧【壓?!?myStack.append(1)
print(myStack)
myStack.append(2)
print(myStack)
myStack.append(3)
print(myStack)
myStack.append(4)
print(myStack) #[1,2,3,4]
#出棧
myStack.pop()
print(myStack)
myStack.pop()
print(myStack)
myStack.pop()
print(myStack)
myStack.pop()
print(myStack)
2.隊列
queue
水平放置的水管:先進先出,后進后出
代碼演示:
import collections #數(shù)據(jù)結(jié)構(gòu)的集合
queue = collections.deque([1,2,3,4])
print(queue)
#入隊【存儲數(shù)據(jù)】
queue.append(5)
print(queue)
queue.append(6)
print(queue)
#出隊【獲取數(shù)據(jù)】
queue.popleft()
print(queue)
queue.popleft()
print(queue)
queue.popleft()
print(queue)