1. is和==的区别
a=[1,2]
b=[1,2]
a==b True
a is b False
==
判断的是内容,[两个人长得是不是一样?]
is
判断的是内存地址,[两个人是不是同一个人]
一般我们用is
来判空c=None if c is None: # if c is not None: print('c => None')
2.*
和**
的作用
# -*- coding: utf-8 -*-
def func(*args): # *放在函数形参中 => 将位置参数聚合成元组
print(args) # ('1', '2', '3')
print(type(args)) # <class 'tuple'>
lst = ['1', '2', '3']
func(*lst) # * 放在函数实参中 => 将可迭代参数【打散】成 位置参数
# -*- coding: utf-8 -*-
def func(**kvargs): # *放在函数形参中 => 将关键字参数聚合成字典
print(kvargs) # {'name': '张三', 'age': 18, 'sex': '女'}
print(type(kvargs)) # <class 'dict'>
v_dic = {'name': '张三', 'age': 18, 'sex': '女'}
func(**v_dic) # * 放在函数实参中 => 将字典参数【打散】成 关键字参数 再进行传递
*
和**
在形参:聚合,把位置参数聚合成元组,把关键字参数聚合成字典
在实参:打散,把可迭代对象转化为位置参数,把字典转化成关键字参数
3.global
和nonlocal
# -*- coding: utf-8 -*-
a = 1
def func():
global a # 当前func函数内部使用的a都是全局的
a += 1
print(a)
func() # 2
print(a) # 2
# -*- coding: utf-8 -*-
def func():
a = 10
def func2():
nonlocal a # 必须在局部,将外层中的xxx变量引入到内层
a += 1
print(a)
func2() # 11
print(a) # 11
func()
4. python 三大器之装饰器
4.1装饰器雏形
装饰器:可以在不改变原来代码的基础上,给函数添加新的功能
可以在原有操作的前面或者后面随意的添加新的功能
# -*- coding: utf-8 -*- def wrapper(func): # 将被装饰的函数传递进来 def inner(): print("被装饰函数执行之前") func() # 执行被装饰的函数 print("被装饰函数执行之后") return inner # 将内层函数返回 def add(): print("执行add函数") a = wrapper(add) # 对a进行打印 # <function wrapper.<locals>.inner at 0x0000026890D8BA60> # 函数类型 wrapper函数.局部类型.inner函数 at 内存地址 print(a) # 对a进行调用 a() """ 被装饰函数执行之前 执行add函数 被装饰函数执行之后 """
# -*- coding: utf-8 -*- def wrapper(func): # 将被装饰的函数传递进来 def inner(): print("被装饰函数执行之前") func() # 执行被装饰的函数 print("被装饰函数执行之后") return inner # 将内层函数返回 def add(): print("执行add函数") add = wrapper(add) # 此时的add就变成了inner # 对add进行打印 # <function wrapper.<locals>.inner at 0x0000026890D8BA60> # 函数类型 wrapper函数.局部类型.inner函数 at 内存地址 print(add) # 对a进行调用 add() """ 被装饰函数执行之前 执行add函数 被装饰函数执行之后 """
""" add = wrapper(add) # 这句话可以被替代为@wrapper [语法糖] """ # -*- coding: utf-8 -*- def wrapper(func): # 将被装饰的函数传递进来 def inner(): print("被装饰函数执行之前") func() # 执行被装饰的函数 print("被装饰函数执行之后") return inner # 将内层函数返回 @wrapper def add(): print("执行add函数") if __name__ == '__main__': add()
4.2通用装饰器
通用装饰器: 有返回值和
# -*- coding: utf-8 -*- def wrapper(func): # 将被装饰的函数传递进来 def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 # 任意的参数都能接受 print("被装饰函数执行之前") ret = func(*args, **kwargs) # 执行被装饰的函数 print("被装饰函数执行之后") return ret # 在func执行之后将结果返回 return inner # 将内层函数返回 @wrapper # add=wrapper(add) def add(name, pwd): print(f"执行add函数 name : {name} pwd :{pwd}") return f"return name : {name} pwd :{pwd}" if __name__ == '__main__': s = add("root", '123456') print(s) # 这样就可以装饰到可边长参数,也就是任意函数上面了
4.3 装饰器示例
在执行目标函数的时候,判断是否登录,如果没有登录,请登录,确保用户在登录成功之后再调用目标函数
# -*- coding: utf-8 -*- flag = False # 默认没有登录 def login(): global flag name = input("请输入姓名\n") pwd = input("请输入密码\n") if name == 'root' and pwd == '123456': flag = True else: flag = False print("账号或者密码输入错误,请重新输入") def login_verify(func): """ 这是注释 在pycharm中打出三个" 然后松开Shift 回车即可 :param func: 被装饰的函数 :return: inner """ def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 while True: # 反复的判断登录状态 if flag: ret = func(*args, **kwargs) # 执行被装饰的函数 print("被装饰函数执行之后") return ret # 在func执行之后将结果返回 else: login() return inner # 将内层函数返回 def wrapper(func): # 将被装饰的函数传递进来 def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 print("被装饰函数执行之前") ret = func(*args, **kwargs) # 执行被装饰的函数 print("被装饰函数执行之后") return ret # 在func执行之后将结果返回 return inner # 将内层函数返回 @login_verify def add(): print(f"执行add函数") return f"return add函数" if __name__ == '__main__': s = add() print(s)
4.4 多个装饰器一起(高阶装饰器)
多个装饰器一起 按照【就近原则】
# -*- coding: utf-8 -*- def wrapper1(func): # 将被装饰的函数传递进来 def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 print("1- 被装饰函数执行之前") ret = func(*args, **kwargs) # 执行被装饰的函数 print("1- 被装饰函数执行之后") return ret # 在func执行之后将结果返回 return inner # 将内层函数返回 def wrapper2(func): # 将被装饰的函数传递进来 def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 print("2- 被装饰函数执行之前") ret = func(*args, **kwargs) # 执行被装饰的函数 print("2- 被装饰函数执行之后") return ret # 在func执行之后将结果返回 return inner # 将内层函数返回 def wrapper3(func): # 将被装饰的函数传递进来 def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 print("3- 被装饰函数执行之前") ret = func(*args, **kwargs) # 执行被装饰的函数 print("3- 被装饰函数执行之后") return ret # 在func执行之后将结果返回 return inner # 将内层函数返回 # 按照就近原则去解读 @wrapper2 @wrapper3 @wrapper1 def add(): print(f"执行add函数") return f"return add函数" if __name__ == '__main__': s = add() print(s)
执行结果
2- 被装饰函数执行之前 3- 被装饰函数执行之前 1- 被装饰函数执行之前 执行add函数 1- 被装饰函数执行之后 3- 被装饰函数执行之后 2- 被装饰函数执行之后 return add函数
分析
首先执行wrapper1 返回w1= 1- 被装饰函数执行之前 执行add函数 1- 被装饰函数执行之后 然后执行 wrapper3 返回w3 w3= 3- 被装饰函数执行之前 w1 3- 被装饰函数执行之后 然后执行 wrapper2 返回w2 w2= 2- 被装饰函数执行之前 w3 2- 被装饰函数执行之后
4.5 带参数的装饰器
装饰器带参数其实就是在装饰器外面又套了个函数壳子
# -*- coding: utf-8 -*- def test_out(name): def wrapper(func): # 将被装饰的函数传递进来 def inner(*args, **kwargs): # 聚合 位置参数和关键字参数 print("被装饰函数执行之前") print(f"开启 {name}") ret = func(*args, **kwargs) # 执行被装饰的函数 print("被装饰函数执行之后") return ret # 在func执行之后将结果返回 return inner # 将内层函数返回 return wrapper # 返回装饰器 @test_out(name="真的吗") def add(): print(f"执行add函数") return f"return add函数" if __name__ == '__main__': s = add() print(s)
输出
被装饰函数执行之前 开启 真的吗 执行add函数 被装饰函数执行之后 return add函数
分析
# 首先执行test_out(name="真的吗") 函数返回一个装饰器 wrapper # 在和前面的@ 一组合形成装饰器 @wrapper @test_out(name="真的吗") def add(): print(f"执行add函数") return f"return add函数"