python之函数

第一章 函数介绍

函数的好处:
1.减少代码重复性 (冗余)
2.代码可读性高
3.将功能进行封装(造工具)

def 关键字 ---定义函数

func 函数名 ---和变量规则一样

()
声明语句结束
def my_len():
    函数体

第二章 函数调用

my_len() 函数名 + ()

def my_len():
  a = "123dsb"
  count = 0
  for i in a:
      count += 1
  print(count)

my_len()  # 函数的调用

第三章 函数的返回值

def num():
    print(1)
    print(2)
    return  "123","321"  #返回的是元组
    print(3)

num()
print(num())

return 的内容返回给函数的调用

遇到return,此函数结束,return下面的代码将不会在执行

return 返回多个内容的时候是元组,调用者可以直接使用解构获取多个变量

return不能终止循环,只能终止函数

return没写返回值,或者干脆就没写return,返回的结果都是是None

第四章 函数的参数

参数,也就是函数括号里的内容 函数在调用的时候指定一个具体的变量的值 就是参数

def 函数名(参数):

    函数体

形参: 函数定义()里的参数

1. 可用位置参数  默认参数 混合参数

实参: 函数调用()里的就是实参

1. 位置参数 关键字参数  混合参数

传参:将实参传递给形参的过程

位置传参时:::::::::实参要与形参一一对应

1.位置参数

def yue(chat):    # chat  形参   

    print("拿出手机")   

    print("打开"+chat)   

    print("找个漂亮的妹子")   

    print("约不约")

yue("陌陌")     # "陌陌"在这里就是实参

2.默认参数

姓名,性别,年龄
def userinfo(name,age,sex="男"):  # 位置参数 > 默认参数
    print(name,sex,age)

count = 5
while count:
    name = input("name:")
    sex = input("sex(男性直接回车!):")
    age = input("age:")
    if sex == "女":
        userinfo(name,age,sex)
    else:
        userinfo(name, age)
    count -= 1

3.关键字参数

def func(a,c,b=1): # a,c位置参数 ,b=1 是默认参数
    print(a,b,c)

func(a=1,b=5,c=2) # a=1,b=5,c=2 是关键字参数

def func(a,b,c):
    print(a,b,c)
func(1,2,c=5) # 混合参数

第五章 三元运算符,枚举

lst =[1,2,3]
def func(b):
    return "da" if len(b)>5 else "xiaoyu"
print(fun(lst))

变量 = 条件成立的结果 条件判断 条件不成立 #####只适用于2个参数

def  dunc():
    lst =[11,22,33]
    dic={}
    for k,v in enumerate(lst,10):  从第十个开始 默认为0
        dic[k]=v
    return dic

第六章 形参的动态函数

1.*args(动态位置参数)

def func(a,b,*args):  #可以接收多个位置参数 可以解说多个 *在定义函数的时候叫做聚合
	print(a,b,args)  #返回的是元组
    #print(a,b,*args)    * 打散  
  
func(1,2,3,4,5)  

######位置参数>动态位置参数>默认参数
def func (*args,a=1,b=2) 

2.**kwargs(动态关键字参数)

def func(a,b,**kwargs):
    print(a,b,kwargs) #返回字典
    #print(a,b,*kwargs) #拿到的是key
  
func(1,2,c=1,d=2)
#1 2 {'c': 1, 'd': 2}
#1 2 c d

3.参数优先级

######位置参数>动态位置参数>默认参数>动态关键字参数
def func(a,b,*args,c=1,d=2,**kwargs):
    print(a,b,args,c,d,kwargs,)
func(1,2,5,4,6,c=3,d=4,e="123",f="22")
#1 2 (5, 4, 6) 3 4 {'e': '123', 'f': '22'}

4.万能参数

#万能传参,可以接受所有的
def func(*args,**kwargs): 
    print(args,kwargs,)
func(1,2,5,4,6,a=1,b=2,c=3)
#(1, 2, 5, 4, 6) {'a': 1, 'b': 2, 'c': 3}
字典和列表打散传入
func(*[1,2,3,4],*[12,2,2,2,2,2],**{1:2,2:3})

5.形参的第四章传参方式,仅限关键字参数

# 
def fun(a,*args,sex="男",c,**kwargs):
    print(a)
    print(args)
    print(sex)
    print(c)
    print(kwargs)
fun(1,3,2,c=4,name="zbb")

第七章 函数的注释

def func1(user,password):
    """
    密码加密
    :param user: 用户名 str
    :param password: 密码 str
    :return: 加密的密码 MD5
    """
    print(user,password)

print(func1.__doc__)

print(func1.__name__)

第八章 名称空间

1.名称空间分类:

  1. 全局空间--> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间
  2. 局部空间--> 在函数中声明的变量会放在局部命名空间
  3. 内置空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间

2.加载顺序

内置 > 全局空间 >局部空间

取值顺序

局部空间 > 全局空间 >内置

都没有就报错

3,作用域

作用域就是作用范围, 按照生效范围来看分为 全局作用域 和 局部作用域

  1. 全局作用域: 全局命名空间 + 内置命名空间
  2. 局部作用域: 局部命名空间

第九章 函数的嵌套

不管在什么位置,只要是函数名+() 就是在调用此函数

函数调用执行后,函数体中开辟的空间就自动销毁了

def func():
    print(1)
    def f1():
        print(2)
    return f1()
print(func())


1.函数互相引用

def func():
    a = 1
    foo()
    print(a)

def foo():
    b = 2
    print(b)
func()

2.global

作用1:在局部作用域中可以更改全局作用域的变量

a=1
def func():
    global a  # 声明修改全局变量的值
    a += 1    
func()
print(a)

global在局部作用域也可以声明一个全局变量。

def func():
    global a
    a = 3
func()
print(a)

3.nonlocal

nonlocal是python3x新加的功能,与global用法差不多,就是在局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal,当然这个用的不是很多,了解即可。

def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def dd_nonlocal():
            nonlocal b
            b = b + 20
            print(b)
        dd_nonlocal()
        print(b)
    do_global()
    print(b)
add_b()

nonlocal :在外层的函数中,修改局部空间的变量值.完全不涉及全局变量,
只修改离它最近的一层,最近的一层没有变量继续向上找,直到找到最外层函数

第十章函数名的使用

函数名是一个变量, 但它是一个特殊的变量, 与括号配合可以执行函数的变量

1.函数名的内存地址

def func():   
    print("呵呵")
print(func)

结果: <function func at 0x1101e4ea0>

2.函数名可以直接赋值给其他变量

def func():   
    print("呵呵")
    print(func)
a = func    # 把函数当成一个值赋值给另一个变量

a()     # 函数调用 func()

3.函数名可以当做容器类的元素

def func1():   
    print("呵呵")
def func2():   
    print("呵呵")
def func3():   
    print("呵呵")
def func4():  
     print("呵呵")

lst = [func1, func2, func3]
for i in lst:  
     i()

4.函数名可以当做函数的参数

def func():   
    print("吃了么")
def func2(fn):   
    print("我是func2")   
    fn()    # 执行传递过来的fn   
    print("我是func2")
func2(func)     # 把函数func当成参数传递给func2的参数fn

5.函数名可以当做函数的返回值

def func_1():   
    print("这里是函数1")   
    def func_2():       
        print("这里是函数2")   
    print("这里是函数1")   
    return func_2
fn = func_1()  
# 执行函数1.  函数1返回的是函数2, 这时fn指向的就是上面函数2
fn()    # 执行func_2函数

6.函数形参可变类型的坑

def extendList(val,list=[]):
    list.append(val)
    return list
print('list1=%s'% extendList(10))
print('list2=%s'% extendList(123,[]))
print('list3=%s'% extendList('a'))
#一步一步的执行,结果可想
#list1=[10]   
#list2=[123]
#list3=[10, 'a']

def extendList(val,list=[]):
    list.append(val)
    return list

list1 = extendList(10)  #执行了
list2 = extendList(123,[])#执行了
list3 = extendList('a')#执行了

print('list1=%s'%list1)
print('list2=%s'%list2)
print('list3=%s'%list3)


#是先执行完所有的 才打印
list1=[10, 'a']
list2=[123]
list3=[10, 'a']

第十一章 f-string字符串格式化

f-strings 是python3.6开始加入标准库的格式化输出新的写法,这个格式化输出比之前的%s 或者 format 效率高并且更加简化

1.举例用法

s= f"我是{'张'}"  #填充字符串
print(s)

# s1 =f"你好{s}" #填充变量
# print(s1)


# s1 = f"{12+13}" #填充计算公式
# print(s1)
# a=10
# b=20
# s1 =f"{a if a>b else b}"  #填充表达式
# print(s1)


print(f"{{73}}")  # {73}
print(f"{{{73}}}")  # {73}
print(f"{{{{73}}}}")  # {{73}}
m = 21
# ! , : { } ;这些标点不能出现在{} 这里面。
# print(f'{;12}')  # 报错
# 所以使用lambda 表达式会出现一些问题。
# 解决方式:可将lambda嵌套在圆括号里面解决此问题。
x = 5
print(f'{(lambda x: x*2) (x)}')  # 10

第十二章 迭代器

1.什么叫迭代?

迭代就是一个重复的过程,每次重复都是基于上一次的结果而来

我们接触到的可迭代对象有

str list tuple dic set range 文件句柄等,int,bool这些不能称为可迭代对象

2.查看对象内部方法

查看是否有str.iter__

s1 = 'alex'
print(dir(s1))
#['__add__', '__class__', ' '__iter__', '__le_,.......]
print('__iter__' in dir(s1))  # True

3.优缺点

优点:

1. 使用灵活

  1. 可以直观的查看里面的数据

缺点:

1.占用内存。

2.可迭代对象不能迭代取值(除去索引,key以外)

2.什么叫迭代器

在python中,内部含有__Iter__方法并且含有__next__方法的对象就是迭代器

f = open('file',encoding='utf-8', mode='w')
print('__iter__' in dir("123"))  # True
print('__next__' in dir("123")  # False

1.可迭代对象如何转化成迭代器:

l1 = [1, 2, 3, 4, 5, 6]
obj = l1.__iter__()
# <list_iterator object at 0x000002057FE1A3C8>
# 或
obj = iter(l1)
print(obj)
# <list_iterator object at 0x102cc67f0>

2.迭代器取值

可迭代对象是不可以一直迭代取值的(除去用索引,切片以及Key),但是转化成迭代器就可以了,迭代器是利用__next__()进行取值:

l1 = [1, 2, 3,]
obj = l1.__iter__()  # 或者 iter(l1)
# print(obj)  # <list_iterator object at 0x000002057FE1A3C8>
ret = obj.__next__()  
print(ret)  #1
ret = obj.__next__()
print(ret)  #2

3.while模拟for的内部循环机制:

#这是假的
s = "121234"
count = len(s)
new_s=iter(s)
while count:
    print(next(new_s))
    count -=1

#异常捕获,不会报错
s = "1234"
new_s=iter(s)
while True:
    try:
        print(next(new_s))
    except StopIteration:
        break


#不写下面的        
    except Exception:
        print("是万能的")
        break

4.优点缺点

优点:

  1. 节省内存。 惰性机制
  2. 迭代器在内存中相当于只占一个数据的空间:因为每次取值都上一条数据会在内存释放,加载当前的此条数据。

缺点:

  1. 一次性的
  2. 不能直观的查看里面的数据。
  3. 取值时不走回头路,只能一直向下取值。
l1 = [1, 2, 3, 4, 5, 6]
obj = iter(l1)

for i in range(2):
    print(next(obj))  # 1,2

for i in range(2):
    print(next(obj))  #3,4


5.总结

应用:当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。

第十二章 递归

  1. 自己调用自己
  2. 有明确的终止条件

满足以上条件才是递归

递:

​ 一直执行到结束条件

def func():
    print(123)
    func()

func()

第十三章 生成器

**生成器的本质就是迭代器 **

迭代器都是(内置的)

Python给你提供的已经写好的工具或者通过数据转化得来的,(比如文件句柄,iter([1,2,3])。

生成器是需要我们自己用python代码构建的工具。

1.生成器的创建方式

在python中有三种方式来创建生成器:

  1. 通过生成器函数
  2. 通过生成器推导式
  3. python内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数而已

2.生成器函数

def func():
    print(11)
    return 22
ret = func()
print(ret)
# 运行结果:
11
22

将函数中的return换成yield,这样func就不是函数了,而是一个生成器函数

def func():
    print(11)
    yield 22
print(func()) #产生生成器
#yield 也是返回

def func():
    print(11)
    yield 22

a=func()  #只是产生了生成器
print(a.__next__())  #这才是调用
#11
# 22

yield会记录执行位置

一个 yield 对应一个__next__()

next超过yield数量,就会报错,与迭代器一样。

def func():
    # print(11)
    yield 22
    yield   44

a=func()
print(a.__next__())
print(a.__next__())

def  zz():
    if 3>2:
        yield 11
    if 2<3:
        yield 22
    yield  33

a=zz()
print(a.__next__())
print(a.__next__())
print(a.__next__())

3.yield与return的区别:

return 可以写多个但是只执行一次,占用内存。

yield可以写多个执行多次,非常的节省内存,而且还可以保留上次的位置。

yield 可以将循环 临时暂停

4.yield from

在把可迭代对象中的每一个数据作为生成器的结果挨个返回

# 对比yield 与 yield from 
def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield lst
g = func()
print(g)
print(next(g))  # 只是返回一个列表
​
def func():
    lst = ['卫龙','老冰棍','北冰洋','牛羊配']
    yield from lst
g = func()
print(g)
# 他会将这个可迭代对象(列表)的每个元素当成迭代器的每个结果进行返回。
print(next(g))
print(next(g))
print(next(g))
print(next(g))
'''
yield from ['卫龙','老冰棍','北冰洋','牛羊配'] 
等同于:
    yield '卫龙'
    yield '老冰棍'
    yield '北冰洋'
    yield '牛羊配'

小坑

返回的结果是将第一个列表的元素全部返回后,在返回第二个列表

def func():
    lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配']
    lst2 = ['馒头', '花卷', '豆包', '大饼']
    yield from lst1
    yield from lst2


g = func()
for i in g:
    print(i)

# 在函数中将return改写成yield就是一个生成器
# yield 会记录执行位置
# return 和 yield 都是返回,
# return 可以写多个,但是只执行一次,yield可以写多个,还可以返回多次
# 一个__next__() 对应 一个yield
# 生成器可以使用for循环获取值
# yield from -- 将可迭代对象元素逐个返回
# 在函数的内部 yield 能将for循环和while循环进行临时暂停

第十四章 推导式

1.列表推导式

1.循环模式:[变量(加工的变量) for 变量 in iterable]

2.筛选模式: [变量(加工的变量) for 变量 in iterable if 条件]

li = []
for i in range(10):
    li.append(i)
print(li)  

循环模式

#升级版本推导式  
print([i  for i in range(20)])

筛选模式

print([i  for i in range(20) if i  %2 == 0])

2.生成器表达式

循环模式

g = (i for i  in range(20))
print(next(g))
print(next(g))

print(list((i for i in range(20))) #转变为列表

筛选模式

g = (i for i  in range(20) if i %2 ==1)
for i in g:
    print(i)

3.字典推导式

print({i:i+1 for i in range(10)})
print({i:i+1 for i in range(10) if i % 2 == 0})
#{键:值 for循环 加工条件}

4.集合推导式

print({i for i in range(10)})
print({i for i in range(10) if i % 2 == 0})

第十五章 内置函数一(了解)

eval:执行字符串类型的代码,并返回最终结果。千万不能使用

eval('2 + 2')  # 4

exec:执行字符串类型的代码。 千万不能使用

for i in [1,2,3]:
    print(i)
'''
exec(s)   
1
2
3

hash:获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。

print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('alex'))
print(hash(True))
print(hash(False))
print(hash((1,2,3)))
#判断时候哈希

help:函数用于查看函数或模块用途的详细说明。

print(help(list))
print(help(str.split))

callable:函数用于检查一个对象是否是可调用的。如果返回True,仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。

name = 'alex'
def func():
    pass
print(callable(name))  # False
print(callable(func))  # True

int:函数用于将一个字符串或数字转换为整型。

print(int())  # 0
print(int('12'))  # 12
print(int(3.6))  # 3
print(int('0100',base=2))  # 将2进制的 0100 转化成十进制。结果为 4

float:函数用于将整数和字符串转换成浮点数。

complex:函数用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。。

print(float(3))  # 3.0
print(complex(1,2))  # (1+2j)

bin:将十进制转换成二进制并返回。

oct:将十进制转化成八进制字符串并返回。

hex:将十进制转化成十六进制字符串并返回。

print(bin(10),type(bin(10)))  # 0b1010 <class 'str'>
print(oct(10),type(oct(10)))  # 0o12 <class 'str'>
print(hex(10),type(hex(10)))  # 0xa <class 'str'>

divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。

round:保留浮点数的小数位数,默认保留整数。

pow:求xy次幂。(三个参数为xy的结果对z取余)

print(divmod(7,2))  # (3, 1)
print(round(7/3,2))  # 2.33
print(round(7/3))  # 2
print(round(3.32567,3))  # 3.326
print(pow(2,3))  # 两个参数为2**3次幂
print(pow(2,3,3))  # 三个参数为2**3次幂,对3取余。

bytes:用于不同编码之间的转化。

# s = '你好'
# bs = s.encode('utf-8')
# print(bs)
# s1 = bs.decode('utf-8')
# print(s1)
# bs = bytes(s,encoding='utf-8')
# print(bs)
# b = '你好'.encode('gbk')
# b1 = b.decode('gbk')
# print(b1.encode('utf-8'))

ord:输入字符找当前字符编码的位置

chr:输入当前编码的位置数字找出其对应的字符

# ord 输入字符找该字符编码的位置
# print(ord('a'))
# print(ord('中'))

# chr 输入位置数字找出其对应的字符
# print(chr(97))
# print(chr(20013))

repr:返回一个对象的string形式(原形毕露)。

# %r  原封不动的写出来
# name = 'taibai'
# print('我叫%r'%name)

# repr 原形毕露
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')

all:可迭代对象中,全都是True才是True

any:可迭代对象中,有一个True 就是True

# all  可迭代对象中,全都是True才是True
# any  可迭代对象中,有一个True 就是True
# print(all([1,2,True,0]))
# print(any([1,'',0]))

print(globals()) 查看全局的变量

print(nonlobals()) 查看局部的

第十六章 内置函数二

高阶函数:内置函数中还可以套函数的函数

常见高阶函数:sorted()、filter()、map()、max()、min()、reduce()

1.abs() #绝对值

返回的都是正数

2.enumerate --枚举

可迭代对象","序号的起始值" # 默认的起始值是0

lst =[1,2,3,4,5]

print([ i  for i in enumerate(lst)])
#[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] 

print(dict([i for i in enumerate(range(20),1)]))

3.max 求最大值

print(max("123")) #可以列表等

4.min 最小值

print(min("123"))

5.sum 求和

print(sum([1,2,3,10],100))

6.print()

#更换链接符
print(1,2,3,4,sep="*")
#1*2*3*4

print(1,end='	')
print(1,end="")
print(1)
#1	11

#项文件中添加
print(12345,file=open("1.txt","w",encoding="utf-8"))

print(dict(key=1,a="alex")) #字典的一种写法

7.zip() 拉链

按照最少的进行合并

lst1 =[1,2,3,4,5]
lst2=['a',"w","q","a","b","qwe"]
print(list(zip(lst1,lst2)))
print(dict(list(zip(lst1,lst2))))  #面试题

第十七章 匿名函数

1.匿名函数

lambda 是一行函数

形参可以不写

返回值必须要写

f=lambda x,y:x+y
print(f(1,2))
print(f.__name__) #查看函数的名字
# lambda #关键字 ---定义函数  就是函数名
# x,y   形参
# x+y  返回值   只能返回一个数据类型

一行调用

print((lambda x,y:x+y)(1,2))

lst =list((lambda i:i*i for i in range(6)))
print(lst[2](3))

lst =list((lambda :i*i for i in range(6)))
print(lst[2]())

第十八章 重要内置函数

1.format

print(format(13,">20"))  #右对齐
print(format(13,"<20"))  #左对齐
print(format(13,"^0"))  #左对齐

print(format(13,"b"))  #2
print(format(13,"d"))  #10
print(format(13,"o"))   #8
print(format(13,"x"))  #16

2.filter过滤

lst =[1,2,3,4,5]
def fun(s):
    return s>3

print(list(filter(fun,lst)))
#fun  过滤条件  lst迭代对象
print(list(filter(lambda x:x,lst)))

3.map()对象映射

print(list(map(lambda x:x+1,[1,2,3,4])))
#对可迭代对象中每个元素进行加工

4.翻转

lst = [1,2,3,4,5]
lst.reverse()
print(lst)

lst1 = list(reversed(lst))
print(lst)
print(lst1)

5.排序sorted

升序

lst = [1,23,34,4,5,213,123,41,12,32,1]
print(sorted(lst))   # 升序
print(lst)

降序

lst = [1,23,34,4,5,213,123,41,12,32,1]
print(sorted(lst,reverse=True))  # 降序

key

dic = {"key":1,"key1":2,"key3":56}
print(sorted(dic,key=lambda x:dic[x],reverse=True))  # key是指定排序规则

print(max([1,2,-33,4,5],key=abs))  # 按照绝对值的大小,返回此序列最小值

6.累计算reduce

累计算

from functools import reduce
# reduce 累计算
print(reduce(lambda x,y:x-y,[1,2,3,4,5]))

第十九章 闭包

1.在嵌套函数中,使用非全局变量 且不是本层的 就是闭包

闭包的作用,保证数据的安全性

例子:

def func():
    a = 1
    def f1():
        def foo():
            print(a)
        return foo
    return f1
# ret = func()
# a = ret()
# a()

func()()()

def func():
    avg_lst = []  # 自由变量
    def foo(pirce):
        avg_lst.append(pirce)
        avg = sum(avg_lst) / len(avg_lst)
        return avg
    return foo
ret = func()

print(ret(150000))
print(ret(160000))
print(ret(170000))
print(ret(150000))
print(ret(180000))
print(ret.__closure__)  #判断是否是闭包

闭包的作用:
1.  保证数据的安全性
2.  装饰器

了解:
print(ret.__code__.co_freevars)  # 获取的是自由变量
print(ret.__code__.co_varnames)  # 获取的是局部变量

第二十章 装饰器

作用在不修改源码及调用方式前提下额外增加一些功能

1.开放原则

1.对扩展是开放的 : 增加新功能

2.对修改是封闭的(修改已经实现的功能)

版本一

测试此函数的执行效率

3.语法

语法糖 -- 甜语法糖必须放在被装饰的函数正上方

标准版(装饰器):
def func(a):  #a是要被装饰的函数名
    def foo(*args,**kwargs):
        "装饰之前的操作"
        ret = a(*args,**kwargs)
        "装饰之后的操作"
        return ret
    return foo
@func
def f1(*args,**kwargs):
    print(f"这是一个{args}")
    return "我可以返回了"
f1(1,2,3,34,4,5)

版本low

import  time
def times(fu):
    def  inner():
        start_time=time.time()
        fu()
        print(time.time() - start_time)
    return inner

def foo():
    time.sleep(3)
    print(12324)

foo = times(foo)
foo()

版本高级

# 高级
import time
def wrapper(f):
    def inner(*args,**kwargs):
        "被装饰前"
        start_time = time.time()
        f(*args,**kwargs) # func("alex")
        print(time.time() - start_time)
        "被装饰后"
    return inner  # 切记不要加括号

@wrapper  # foo = wrapper(foo)
def foo(*args,**kwargs):
    print(f"这是{args}函数")
    time.sleep(3) #模拟网络延时
# foo = wrapper(foo)
foo("al","su")

第二十一章 带参数的装饰器

装饰器其实就是一个闭包函数,再说简单点就是两层的函数

举例

./

def auth(argv):
    def wrapper(func):
        def inner(*args,**kwargs):
            func(*args,**kwargs)
        return inner
    return wrapper

login_dic={
    "flag":False,
    "username":None
}

def auth(argv):
    def wrapper(func):
        def inner(*args,**kwargs):
            if login_dic["flag"]:
                func(*args,**kwargs)
            else:
                if argv == "QQ":
                    print("欢迎登陆QQ")
                    user = input("username")
                    pwd = input("password")
                    if user == "zbb" and pwd=="zbb123":
                        login_dic["flag"] =True
                        login_dic["username"]=user
                        func(*args,**kwargs)
                    else:
                        print("用户名,密码")
        return inner
    return wrapper

@auth("QQ")
def foo():
    print("qq登录")

# wrapper = auth("QQ")
# foo = wrapper(foo)
foo()

第二十二章 多个装饰器装饰一个参数

def wrapper1(func):
    def inner1(*args,**kwargs):
        print(1)
        func(*args,**kwargs)
        print(11)
    return inner1

def wrapper2(func):  # func == foo
    def inner2(*args,**kwargs):
        func(*args, **kwargs)
        print(22)
    return inner2

def wrapper3(func):
    def inner3(*args,**kwargs):
        print(3)
        func(*args, **kwargs)
        print(33)
    return inner3
@wrapper1  # 1 11
@wrapper3  # 3 33
@wrapper2  #  8 22

def foo():
    print(8)

# foo = wrapper2(foo)  # foo == inner2
# foo = wrapper3(foo)  # inner3 = wrapper3(inner2)
# foo = wrapper1(foo)  # inner1 = wrapper1(inner3)
foo()   


原文地址:https://www.cnblogs.com/zdqc/p/11197913.html