global与nonlocal关键字使用

x = 1
def func():
		# 局部修改成全局 如果不加这行代码print输出的是1
    global x
    x = 2
func()
print(x)  # 2

"""
如果想在局部修改全局数据
    如果数据为不可变类型则需要关键字global声明
    如果数据为可变类型则无需关键字global声明
"""
name_list = ['tpny', 'jason']
def index():
    name_list.append('okkk')
index()
print(name_list)  # ['tpny', 'jason', 'okkk']

"""
如果想要在内部的局部修改外部局部的不可变类型数据
需要关键字nonlocal声明
"""
def index():
    x = 1
    def func():
        # 内部局部修改外部局部
        nonlocal x
        x = 2
    func()
    print(x)
index()

# 可变类型不需要加nonlocal
def index():
    l1 = [11,22]
    def func():
        l1.append(333)
    func()
    print(l1)
index()

函数对象(函数名)

"""函数名遇到括号就会调用"""
# 用法1:函数名可以当作变量名赋值
def index():
    print('from index')
a = index
print(a)  # <function index at 0x10e155f28>
a()  # from index
res = a()  # from index 虽然是赋值但也相当于调用了函数index,只要函数名加括号就是一次调用
print(res)  # None

# 用法2:函数名还可以当作函数的实参
def index():
    print('from index')
def func(a):
    print(a)  # <function index at 0x10f1eaf28> 先输出index函数名的地址
    a()  # a即index 调用index()函数 输出 from index
    print('from func')  # 最后执行这句 from func
func(index)

		# 错误
  
    def func():
        print('from func')
    def index(a):
        print(a)
        a()  # 调用函数a
        print('from index')
    index(a)  #  TypeError: name 'a' is not defined
    index('qwe')  # TypeError:'str' object is not callable 填的实参要是可被调用的函数名!!
    

# 用法3:函数名还可以当作函数返回值
def index():
    print('from index')
def func():
    print('from func')
    return index
res = func()  # 把func函数的返回值赋给res,然后因为有括号 所以先调用运行func函数
res()  # 实际上是index()

# 用法4:函数名可以当作容器类型的元素
def index():
  	print('from index')
l = [111,222,333,index()]
print(l)

函数的嵌套调用

# 嵌套调用:函数内部调用其他函数
def index():
  	print('from index')
def func():
  	index()
    print('from func')
func()

# 比较大小
def num(a, b):
    if a > b:
        return a
    return b
def num1(x, y, z, m):
    res = num(x, y)
    res2 = num(res, z)
    res3 = num(res2, m)
    return res3
result = num1(1, 3, 2, 6)
print(result)

函数的嵌套含义

函数体内部定义其他函数

将复杂的功能全部隐藏起来,暴露一个简单的接口

def all_func(type):
    def register():
        print('注册功能')
    def login():
        print('登录功能')
    def transfer():
        print('转账功能')
    def shopping():
        print('购物功能')
    # 这里仅仅是延时嵌套定义的现象 暂不考虑优化
    if type == '1':
        register()
    elif type == '2':
        login()
    elif type == '3':
        transfer()
    elif type == '4':
        shopping()
    else:
        print('不知道啥功能')

all_func('3')

闭包函数

  • 闭:定义在函数内部的函数
  • 包:内部函数使用了外部函数名称空间中的名字

只有符合上述两个特征的函数才可以称之为“闭包函数”

def outer():
    x = 1
    def index():
      	print('from index',x)
    return index

闭包函数其实是给函数传参的第二种方式

给函数传参方式1:函数代码需要用到数据,直接在括号内定义形参即可

def index(username):
		print(username)

def func(a,b):
  	if a > b:
      	return a
    return b

方式2:利用闭包函数

def outer(x,y):
  #	x = 1
  #  y = 20
    def my_max()
    	if x > y:
        	return x
      return y
    return my_max
res = outer(2,40)
print(res())

装饰器

  • 器:指的是工具
  • 装饰:给被装饰的对象添加额外功能

装饰器的原则

开放封闭原则

开放:对扩展开放,封闭:对修改封闭

装饰器核心思想

在不改变被“装饰对象内部代码”和“原有调用方法”的基础之上添加额外功能

def index():
  	print('from index')
index()
# 统计index函数的执行时间


import time

print(time.time())  # 1637036293.0609405
# 获取的结果叫时间戳(运行代码的那一刻距离1970-1-1所经历的秒数)
time.sleep(3)  # 让程序原地等待3秒
print('睡饱了')


def index():
    time.sleep(3)
    print('from index')
# 统计index函数的执行时间
# 在函数运行之前统计一次时间
start_time = time.time()
index()
# 在函数运行完毕之后再次统计
end_time = time.time()
# 计算差值
print(end_time - start_time)