Python入门8

高阶函数

map(fun, range(1,11))
主要理解执行的过程及分析—-高阶函数,返回值是一个函数(定义函数并不会执行函数内容, 调用时才会执行.)

def compare1(base):                           # base=10
    def compare2(y):                          # y=3
        return base > y                       # 10>3 True
    return compare2                           # compare2===函数名

compare_base_10 = compare1(10)
print(compare_base_10)                        # 函数名
res = compare_base_10(3)
print(res)

print(abs)
def add(x,y):
    return x+y
print(add)

这里写图片描述

装饰器

模拟ATM
用户使用ATM的时候, 执行程序之前祝福语==“国庆节快乐”,
执行程序之后打个广告====”欢迎再次光临西部开源…..”.
1. 解决问题: 在函数执行之前和执行之后添加功能, 调用函数的方式改变了.
2. 不改变原有函数的调用方法: 函数里面嵌套函数, 并且返回嵌套的函数login = desc(login)

def desc(fun):       # fun = login 需要传递一个函数, 要装饰的函数
    def add_info( ):               装饰器函数里面嵌套函数
        print("五一快乐")
        fun( )                     # login( )
        print("欢迎再次光临西部开源.....")
    return add_info                返回值是嵌套的函数对象

#### 语法糖
@desc       # login = desc(login)   如何调用装饰器(两种方式)
def login( ):
    # print("国庆节快乐")
    print("login......")
    # print("欢迎再次光临西部开源.....")
 #login = desc(login)                 # 返回值是一个函数
 #login( )
login( )

def logout( ):
    print("logout......")

logout = desc(logout)
logout( )
def saveMoney():
    print("存钱........")

def transferMoney():
    print("转账.........")

 几百个函数, 此处省略......
 add_info(login)

这里写图片描述

装饰器实现一个计数器

装饰器需求: 获取每个函数的执行时间
1).函数执行之前计算时间;
2).函数执行之后计算时间

实验1:看字符串拼接的效率
1). “hello” + “world”
2). ” “.join([‘hello’, “world”])

实验2:检测列表生成式和map的效率高低, n为函数传入的参数两者实力相当
1). [n*2 for i in range(n)]
2). map(lambda x:x*2, range(n))

import random
import string
import time
li = [ random.choice(string.ascii_letters) for i in range(100)]

def timeit(fun):                                      # fun_list
    def wrapper(*args, **kwargs):       # 接收可变参数和关键字参数
        # args: 元组   kwargs: 字典  args=(5,)
        # 函数执行之前
        start_time = time.time()
        # 执行函数
        fun(*args, **kwargs)            # args解包, 5,|  对于元组解包, 对于字典解包
        # 执行函数之后
        end_time = time.time()
        print("运行时间为:%.6f" % (end_time - start_time))
    return  wrapper
@timeit
def con_add( ):
    s = ''
    for i in li:
        s += (i+",")
    print(s)
@timeit
def join_add():
    print(",".join(li))


@timeit            #fun_list=timeit(fun_list) fun_list = wrapper
def fun_list(n):
    print([2*i for i in range(n)])
@timeit
def fun_map(n):
    print(list(map(lambda x:x*2, range(n))))

con_add( )
join_add( )
fun_list(500000)   
fun_map(500000)

这里写图片描述
这里写图片描述

装饰器之函数属性变化解决方案

import random
import string
import time
import functools

高阶函数的一些方法

from functools import reduce

问题1: 装饰的函数有返回值的解决方法:
问题2:如何保留被装饰函数的函数名和帮助文档信息. @functools.wraps(fun)

def timeit(fun):           # fun_list
    """这是一个装饰器timeit"""
    @functools.wraps(fun)
    # 可以保留被装饰函数的函数名和帮助文档信息.
    def wrapper(*args, **kwargs):   # 接收可变参数和关键字参数  # 100
        #这是一个wrpper函数
        # args: 元组   kwargs: 字典  args=(100,)
        # 函数执行之前
        start_time = time.time()
        # 执行函数
        res = fun(*args, **kwargs)  # args解包, 100,|  对于元组解包, 对于字典解包
        # fun_list(100)
        # 执行函数之后
        end_time = time.time()
        print("运行时间为:%.6f" % (end_time - start_time))
        return res
    return  wrapper

@timeit         # fun_list=timeit(fun_list)  # fun_list = wrapper
def fun_list(n):
    #这是fun_list函数, 被timeit装饰
    return [2*i for i in range(n)]

@timeit
def fun_map(n):
   #这是fun_map函数
    return   map(lambda x:x*2, range(n))

@timeit
def fun():
    print("hello")

 print(fun_list(100))           # wrapper(100)
 print(fun_map(100))
 fun( )
print(fun_list.__name__)
print(fun_list.__doc__)

这里写图片描述
添加日志
创建装饰器, 要求如下:
1. 创建add_log装饰器, 被装饰的函数打印日志信息;
2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx

import functools
import time
 #format
def add_log(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):
        # run_time = time.ctime()
        # fun_name = fun.__name__
        start_time = time.time()
        res = fun(*args, **kwargs)
        end_time = time.time()
        print("[%s] 函数名: %s, 运行时间:%.5f, 运行返回值结果:%d"
              %(time.ctime(), fun.__name__, end_time-start_time, res )
              )
        return res
    return wrapper

@add_log
def add(x,y):
    time.sleep(0.1)
    return x+y
print(add(1,2))

这里写图片描述
装饰器的第二种方式
需求: 用户登陆验证的装饰器is_login
1). 如果用户登陆成功, 则执行被装饰的函数;
2). 如果用户登陆不成功, 则执行登陆函数

import functools
login_users = ['admin', 'root']

def is_login(fun):         # fun: writeBlog
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):   # name="admin"  # kwargs={"name":"admin"}
        # 判断写博客的这个用户是否登陆成功;
        if kwargs.get("name") in login_users:
            res = fun(*args, **kwargs)
            return res
        else:
            res=login()
        return res
    return wrapper

 必须登陆成功
@is_login    # writeBlog = is_login(writeBlog)
def writeBlog(name):
    return "编写博客"

def login():
    return "登陆....."

是否登陆成功都可以执行代码
def news():
    print("新闻......")
print(writeBlog(name="admin1"))

这里写图片描述
判断变量的数据类型
编写装饰器required_ints, 条件如下:
1). 确保函数接收到的每一个参数都是整数;
2). 如果参数不是整形数, 打印 TypeError:参数必须为整形

import functools
def required_ints(fun):
    @functools.wraps(fun)
    def wrapper(*args, **kwargs):       # args=(1,2)
        for i in args:                                # i=1
            # if isinstance(i, int):
            #     pass
            # else:
            #     print("函数所有参数并非为整形")
            #     break
            if not isinstance(i , int):
                print("函数所有参数并非为整形")
                break
        else:
            res = fun(*args, **kwargs)
            return  res
    return wrapper

@required_ints
def add(a, b):
    return a + b
print(add(1,2.0))

这里写图片描述
这里写图片描述
带有参数的装饰器
创建装饰器, 要求如下:
1. 创建add_log装饰器, 被装饰的函数打印日志信息;
2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx

import functools
import time

 format
def log(kind):  # kind="debug"
    def add_log(fun):
        @functools.wraps(fun)
        def wrapper(*args, **kwargs):
            # run_time = time.ctime()
            # fun_name = fun.__name__
            start_time = time.time()
            res = fun(*args, **kwargs)
            end_time = time.time()
            print("<%s> [%s] 函数名: %s, 运行时间:%.5f, 运行返回值结果:%d"
                  %(kind, time.ctime(), fun.__name__, end_time-start_time, res )
                  )
            return res
        return wrapper
    return  add_log
@log("debug")
  log("debug")==> 返回值是add_log
  add=add_log(add)
def add(x,y):
    time.sleep(0.1)
    return x+y
print(add(1,2))
wrapper(1,2)

这里写图片描述

装饰器总结

装饰器的概念
- 装饰器的实现是函数里面嵌套函数;
- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;
- 装饰器需要传递一个函数, 返回值也是一个函数对象.
-计时器
-记录日志
-用户验证
-函数参数验证

猜你喜欢

转载自blog.csdn.net/qq_42725815/article/details/81945480