Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列)
一丶带参数的装饰器
def wrapper_out(pt):
def wrapper(func):
def inner(*args,**kwargs):
useinput = input('请输入用户名:>>').strip()
password = input('请输入密码:>>').strip()
with open(pt,encoding='utf-8') as f:
for line in f:
us,pwd=line.strip().split('|')
if useinput==us and password ==pwd:
print(f'登录{pt}成功')
ret=func()
return ret
return False
return inner
return wrapper
@wrapper_out('qq')
def QQ():
print('welcome QQ')
@wrapper_out('dy')
def Dy():
print('welcome Dy')
QQ()
Dy()
### 看到带参数的装饰器分两步执行:
#开发思路:增强耦合性
# @wrapper_out('qq')
# 1. 执行wrapper_out('qq') 这个函数,把相应的参数'qq' 传给 pt,并且得到返回值 wrapper函数名。
# 2. 将@与wrapper结合,得到我们之前熟悉的标准版的装饰器按照装饰器的执行流程执行。
二丶多个装饰器装饰一个函数
def wrapper1(func1):
def inner1():
print('w1 ,before')
func1()
print('w1 after')
return inner1
def wrapper2(func2):
def inner2():
print('w2 ,before')
func2()
print('w2 after')
return inner2
@wrapper2 # f =wrapper2(f) , func2=inner1函数 当执行完func2时, 就带表要去执行inner1, func1() 执行的是真正的原函数.
@wrapper1 # f =wrapper1(f) , func1=f原函数 f()=inner1
def f():
print('in f')
f() # f在这里 被我定义 变量,看下面理解,就ok了.
#### 推荐一种方式 ,debug模式.
# 多个装饰器装饰一个函数相当于装饰器函数的嵌套 (相当于把另一个装饰器函数的inner方法作为参数传递给了另一个装饰器函数的形参func接收.) so不明白就看下面吧👇
# 1. 程序从上到下执行, 加载两个函数到内存. ---> 按常理来说应该是先执行wrapper2 ,但是由于wrapper1 靠近被装饰的函数. so 先执行 wrapper1装饰器函数
# 2. 执行 wrapper 1装饰器, func1 形参接收的是 f原函数的内存地址, 而f(变量)被指向为--->inner1函数内存地址
# 3. 指向wrapper2 装饰器 , func2 形参接收的是 f(变量的内存地址 ,也就是inner1的内存地址), 此时的f(变量)被重新指向为 inner2 函数的内存地址.
# 加载执行过程:
f(变量)--->inner1,func1形参--->f原函数 ==========>>>> f(变量)----<inner2 ,func2形参---->inner1(inner1函数内存地址被当做参数传给了func2)
# 取值执行过程:
f(变量)就是inner2 函数执行, ----> 打印w2 before -->执行 func2, 也就是执行inner1函数,打印w1 before
----->执行func1形参的值,func1指向的 f原函数 ,打印 f原函数内的东西 ----> 执行完原函数后,返回到inner1函数继续执行----->打印inner1函数 w1 after .------> 执行完inner1函数,返回到inner2函数中,打印 w2 after
###总结快捷解题规律: (最好是画图,快捷, 没有之一.)
# 1.哪个装饰器在被装饰器函数的最上面. 那个就是最外层.
# 2.一层一层嵌套. 如下图👇:
三丶递归函数
# -*- coding: utf-8 -*-
# Author : Ds
# 递归函数 : 函数或者其他的代码都可以解决 递归解决的问题 .递归在某些时候有特效
# 官网规定: 默认递归的最大深度1000次
# 如果你递归超过100次还没有解决这个问题,那么执行使用递归,执行效率低
#递归含义:
# 具有明确的终止条件
# 自己调用自己
#递归案例一:
def func(n):
print(n)
n+=1
func(n)
func(1)
#递归案例二:
def age(n):
if n ==1:
return 18
else:
return age(n-1)+2
print(age(4))
#递归案例三:
li= [1, 3, 5, ['太白','元宝', 34, [33, [11,33],55, ]], [77, 88],66]
def func(lis):
for el in lis:
if type(el)==list:
func(el)
else:
print(el)
func(li)
# return案例
li= [1, 3, 5, ['太白','元宝', 34, [33, [11,33],55, ]], [77, 88],66]
def func(lis):
for el in lis:
if type(el)==list:
return func(el) # 只执行到最深的一层列表就返回.
else:
print(el)
func(li)
###个人总结:
# 递归函数 中 , 存在return ,若果 递归函数中首先已经明确 结束条件. 在不适当的位置加了return(人为的终止条件) 就会造成数据的缺失,
###存在return
#上述例子中, 如果在 条件判断后,return 返回func()函数,
#(个人理解: 简单的例子,for循环嵌套, 外层需要执行9次 ,但是执行到4,内层需要执行9次,内层执行完9次之后.存在return ,执行完内层的9次就直接终止)
# 那么当列表中的数据遇到最深的一层列表,输出完结果就会直接终止函数. 后面的数据就不在被执行
# 也就是说 return就只执行到最深的一层列表.
###不存在return
# 相反,没有return , (个人理解: 简单的例子,for循环嵌套, 外层需要执行9次 ,但是执行到4,内层需要执行9次,内层执行完9次之后.外层继续执行)
# 每次调用递归, 当内层列表都被打印出来之后,外层列表继续下一次
四丶斐波那契数列的几种推导方式
###斐波那契数列的几种推导方式
#递归:
def fbnq_dg(n):
if n<=1: # 4 逐层递减, 递减拼接相加 ,结束条件是每次的结果值不能小于0,也不能大于1
return n
return fbnq_dg(n-1)+fbnq_dg(n-2) # [3 2] -->, [2 1 1 0], [(1, 0) (0,0) (1,0) (1,0) ] , 特点: 一生二,二生四,四生八 ,将最后的所有1相加.就是结果
for i in range(1,4):
print(fbnq_dg(i))
# 递推
def fib_loop(n):
a,b=0,1
for i in range(n+1):
a,b=b,a+b
return a
print(fib_loop(4)) # 1 1 2 3 5
#生成器
def fib_lop_while(n):
a,b=0,1
while n>0:
a,b=b,a+b
yield a
n -= 1
obj=fib_lop_while(10) # 生成器 <generator object fib_lop_while at 0x000002898FDFFF68>
print(obj.__next__()) # 1 一次取值,打印一次
print(obj.__next__()) # 1
print(obj.__next__()) # 1