函数对象

  • 函数对象指的是函数可以被当做’数据’来处理,具体可以分为四个方面的使用

函数可以被引用

def add(x, y):
	return x + y
func = add
func(1, 2) # 3

函数可以作为容器类型的元素

>>> def add(x,y):
...     return x+y
...
>>> func=add
>>> func(1,2)
3

函数可以作为参数传入另外一个函数

>>> dic={'add':add,'max':max}
>>> dic
{'add': <function add at 0x100661e18>, 'max': <built-in function max>}
>>> dic['add'](1,2)
3

函数的返回值可以是一个函数

>>> def foo(x,y,func):
...     return func(x,y)
...
>>> foo(1,2,add)
3

闭包函数

闭包函数简介

  • 闭包函数:在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包
    1. 定义在函数内部的函数
    2. 内部函数使用了外部函数
    • 只有符合这两个特征的函数才能称为闭包函数
def func():
    username = 'jason'
    def index():
        print(username)
    return index
res = func()
print(res)
res() # jason

def func(username):
    def index():
        print(username)
    return index
func('jason')

闭包函数实际应用

# 给函数体代码传值的方式一:通过形参传值
def func(xxx):
	print(xxx)
# 给函数体代码传值的方式2:闭包函数
def index():
	username = 'jason'
	def func():
		print(username)
	return func
res = index('jason')
res()

装饰器

装饰器简介

  • 装饰器:函数知识整合到一块的产物
  • 装饰器本质:在不改变装饰对象原来的‘调用方式’和‘内部代码’的情况下给被装饰的对象添加功能
  • 装饰器原则:对修改封闭,对扩展开放
  • 知识储备
import time
print(time.time())  # 1656987566.7260265
# 时间戳(秒数):当前距离1970年1月1日0时0分0秒所经历的秒数
# 实际应用:统计代码的运行时间
start_time = time.time()  #  100
for i in range(100000):
    print(i)
end_time = time.time()
print('for循环的执行时间是: %s '%(end_time - start_time))
time.sleep(3) # 让程序等待三秒
print('睡不醒,我好困')

装饰器前期推导

import time
def index():
    time.sleep(3)
    print('from index')
# 统计index函数的执行时间
start_time = time.time() # 在调用index函数之前获取一下时间戳
index() # 调用index函数
end_time = time.time()
print(end_time - start_time)
  • 缺陷:如果有多个index需要统计时间,则需要重新编码
  • 解决措施:封装成函数
import time
def index():
    time.sleep(3)
    print('from index')
def get_time():
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
    index()  # 调用index函数
    end_time = time.time()
    print('函数的执行时间是:', end_time - start_time)
get_time()
  • 缺陷:如果有多个不同的函数需要统计时间 那么上述的解决措施不够完善
  • 解决措施:给函数体添加形参(动态传参)
import time
def index():
    time.sleep(3)
    print('from index')

def home():
    time.sleep(5)
    print('from home')

def get_time(xxx):
    start_time = time.time()  # 在调用index函数之前获取一下时间戳
    xxx(*args, **kwargs)  # 调用index函数
    end_time = time.time()
    print('函数的执行时间是:', end_time - start_time)
get_time(index)
get_time(home)
  • 缺陷:不同形参个数的函数无法兼容统计
  • 解决措施:*args ** kwargs,目前的代码中无法实现(暂且忽略)
import time

def func1(a):
    time.sleep(1)
    print('from func1')
get_time(func1)
  • 缺陷:改变了原来的调用方式
  • 解决措施:装饰器推导流程

装饰器各种版本

import time

"""针对有参无参函数如何兼容"""


def outer(xxx):
    def get_time(*args, **kwargs):
        start_time = time.time()  # 在调用index函数之前获取一下时间戳
        res = xxx(*args, **kwargs)  # 调用index函数
        end_time = time.time()
        print('函数的执行时间是:', end_time - start_time)
        return res

    return get_time


def home():
    time.sleep(2)
    print('from home')
    return '执行home函数之后的返回值'


def index(name):
    time.sleep(1)
    print('from index')
    return '执行index函数之后的返回值'


home = outer(home)
xxx = home()
print(xxx)

index = outer(index)
res = index('jason')
print(res)

home = outer(home)
home()


def func(a, b, c):
    time.sleep(1)
    print('from func')


index = outer(index)
index('jason')

home = outer(home)
home()

func = outer(func)
func(1, 2, 3)

装饰器的固定模板

from functools import wraps
def outer(func_name):
    @wraps(func_name)  # 仅仅是为了让装饰器不容易被别人发现 做到真正的以假乱真
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的额外操作')
        res = func_name(*args, **kwargs)
        print('执行被装饰对象之后可以做的额外操作')
        return res
    return inner

import time
def home():
    time.sleep(1)
    print('from home')
    return 'home返回值'

home = outer(home)
res = home()
print(res)
  • 装饰器语法糖
import time

@outer  #  home = outer(真正的函数名home)
def home():
    '''我是home函数 我要热死了!!!'''
    time.sleep(1)
    print('from home')
    return 'home返回值'

help(home)
print(home)
home()

def index():
    '我是index函数 我的功能很强大'
    pass
help(index)
 posted on 2022-07-05 18:39  念白SAMA  阅读(25)  评论(0)    收藏  举报