python全栈学习--day12(函数高级应用-带参数的装饰器,多个装饰器装饰一个函数)...

函数的执行时,*打散

函数的定义时,*聚合

from functools import  wrapsdef wrapper(f):@wraps(f)def inner(*args,**kwargs):'''执行函数之前的相关操作'''ret = f(*args,**kwargs)'''执行函数之后的相关操作'''return retreturn inner
@wrapper
def func1(*args):print(666)return args
print(func1(*[1,2,3]))
一,函数的有用信息
1.函数名 使用__name__方法
2.函数的解释 使用__doc__方法获取
举个例子:
def func1():"""此函数是完成登陆的功能,参数分别是...作用。:return: 返回值是登陆成功与否(True,False)"""print(666)# print(func1.__name__)# print(func1.__doc__)return True
func1()
print(func1.__name__) #获取函数名
print(func1.__doc__) #获取函数名注释说明

执行输出:

666
func1

此函数是完成登陆的功能,参数分别是...作用。
:return: 返回值是登陆成功与否(True,False)

这个有什么用呢?比如日志功能,需要打印出谁在什么时间,调用了什么函数,函数是干啥的,花费了多次时间,这个时候,就需要获取函数的有用信息了

 带装饰器的函数

def wrapper(f):  # f = func1def inner(*args, **kwargs):  # 聚合# args (1,2,3)'''执行函数之前的相关操作'''ret = f(*args, **kwargs)  # 打散 1,2,3'''执行函数之后的相关操作'''return retreturn inner@wrapper
def func1():"""此函数是完成登陆的功能,参数分别是...作用。:return: 返回值是登陆成功与否(True,False)"""print(666)return Truefunc1()
print(func1.__name__)
print(func1.__doc__)

 此函数是完成登陆的功能,参数分别是...作用。
:return: 返回值是登陆成功与否(True,False)

 

二, 带参数的装饰器

#带参数的装饰器
import time
def timmer(*args,**kwargs):def wrapper(f):print(args,kwargs) #接收第一步的值def inner(*args,**kwargs):if flag:start_time = time.time()ret = f(*args,**kwargs)time.sleep(0.3)end_time = time.time()print('此函数的执行效率{}'.format(end_time-start_time))else:ret = f(*args,**kwargs)return retreturn innerreturn wrapper
flag = True
@timmer(flag,2,3)  #两部:1.timmer(flag,2,3)相当于执行wrapper 2.@wrapper 装饰器 func1 = wrapper(func1)
def func1(*args,**kwargs):return 666
print(func1())

  

执行输出:

(True, 2, 3) {}
此函数的执行效率0.300183

666

函数执行过程分析

import time  #1.加载模块
def timmer(*args,**kwargs): #2.读取timer这个函数变量名到内存中 #5.接收参数True 2, 3def wrapper(f):  #8.f = func1print(args,kwargs) #9.接收timmer函数的值True,2,3def inner(*args,**kwargs): #10. 加载变量 13.执行函数innerif flag:                #14.flag = Truestart_time = time.time() #15获取当前时间ret = f(*args,**kwargs)#16执行func1time.sleep(0.3)         #19等待3秒end_time = time.time()  #20获取当前时间print('此函数的执行效率{}'.format(end_time-start_time)) #21打印差值else:ret = f(*args,**kwargs)   #22返回给函数调用者func(1)return retreturn inner #11.返回给函数调用者wrapperreturn wrapper  #7.返回给函数调用者timmer(flag,2,3)
flag = True #3.加载变量
@timmer(flag,2,3)  #4.执行函数timeer(flag,2,3)  17.执行函数func1   两步:1.timmer(flag,2,3)相当于执行wrapper 2.@wrapper 装饰器 func1 = wrapper(func1)
def func1(*args,**kwargs):return 666      #返回给函数调用者
print(func1()) #12.执行函数

  

假定现在有100个函数,都加上了装饰器,增加了显示函数执行时间的功能,现在需要去掉!

怎能办?一行行代码去删除吗?太low了。

这个时候,直接在装饰器函数加一个参数即可。

import time
flag = False
def wrapper(f):def inner(*args,**kwargs):if flag:start_time = time.time()ret = f(*args,**kwargs)time.sleep(0.3)end_time = time.time()print('此函数的执行效率%f' % (end_time-start_time))else:ret = f(*args, **kwargs)return retreturn inner@wrapper
def func1(*args,**kwargs):print(args,kwargs)return 666
print(func1())

  

现在需要关闭显示执行时间

直接将flag改成false

import time
flag = False
def wrapper(f):def inner(*args,**kwargs):if flag:start_time = time.time()ret = f(*args,**kwargs)time.sleep(0.3)end_time = time.time()print('此函数的执行效率%f' % (end_time-start_time))else:ret = f(*args, **kwargs)return retreturn inner@wrapper
def func1(*args,**kwargs):print(args,kwargs)return 666
print(func1())

  

执行输出:

() {}
666

 

这样,所有调用的地方,就全部关闭了,非常方便

写装饰器,一般嵌套3层就可以了

实例二

a = 5
def func1():a += 1print(a)
func1()

执行报错

这里函数对全局变量做了改变,是不允许操作的。

函数内部可以引用全局变量,不能修改。如果要修改,必须要global一下

a = 5
def func1():global aa += 1print(a)
func1()

  执行输出: 6

三,多个装饰器,装饰一个函数

def wrapper1(func):def inner1():print('wrapper1,before func')func()print('wrapper1 ,after func')return inner1def wrapper2(func):def inner2():print('wrapper2 ,before func')func()print('wrapper2,after func')return inner2@wrapper2
@wrapper1
def f():print('in f')
f()

  

执行输出:

wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func

执行顺序如下图:

多个装饰器,都是按照上图的顺序来的

今日练习作业:

1.写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组

例如:[('红心'2),('草花'2), …('黑桃''A')]
#实例一:
#思路:使用for循环先遍历出红心,黑桃,梅花,方块,再将使用for循环变量1-13个数字
#步骤1:准备基础数据
#颜色
#扑克牌的4种颜色
colour = ['黑桃♠','红心♥','梅花♣','方块♦']
#牌面的值
card = list[range(2,11) + ['A','J','Q','K']]

  

#1.2使用for 循环遍历
# 颜色
colour = ['黑桃♠', '红心♥', '梅花♣', '方块♦']# 牌面的值
card = list(range(2, 11)) + ['A', 'J', 'Q', 'K']
#
for i in card:for j in colour:print((j,i))

  执行输出:

('黑桃♠', 2)
('红心♥', 2)
('梅花♣', 2)

1.3封装成函数

def poker(*args, **kwargs):show_card = []for i in kwargs['card']:for j in kwargs['colour']:show_card.append((j, i))return show_card
print(poker(colour=colour, card=card))

  

执行输出:

[('黑桃♠', 2), ('红心♥', 2), ('梅花♣', 2),...]

2.写函数,传入n个数,返回字典{'max':最大值,'min':最小值}
例如:min_max(2,5,7,8,4)
返回:{'max':8,'min':2}

2.1直接使用内置函数,可以得到最大值和最小值
a = (1,2,3)
b = {'k1':1,'k2':2}
print(max(a))
print(min(b.values()))

  

执行输出:

3
1

 

2.2封装成函数

def min_max(*args,**kwargs):dic = {'max':None,'min':None}number = []#循环位置变量for i in args:    #这里是接收数据for j in i:   #这里是迭代数据,打散将每一个数字分成变量一个元素number.append(j)#循环关键字变量for k in kwargs.values():number.append(k)#最大值和最小值dic['max'] = max(number)dic['min'] = min(number)return dicprint(min_max([2,3,4,5,6,9],a=8))

  执行后输出:

{'max': 9, 'min': 2}

3.写函数,专门计算图形的面积
其中嵌套函数,计算圆的面积,正方形的面积和长方形的面积
调用函数area('圆形',圆半径) 返回圆的面积
调用函数area('正方形',边长) 返回正方形的面积
调用函数area('长方形',长,宽) 返回长方形的面积
def area():
def 计算长方形面积():
pass

def 计算正方形面积():
pass

def 计算圆形面积():
pass

先找出公式


长方形面积公式
S = ab
公式描述:公式中a,b分别为长方形的长和宽,S为长方形的面积。

正方形面积公式
S = a²
公式描述:公式中a为正方形边长,S为正方形面积。

圆的面积公式
S = πr²
公式描述:公式中r为圆的半径,π用3.14表示

def area(*args,**kwargs):#计算长方形面积def rectangle(*args,**kwargs):#print(args)return args[0] * args[1]#计算正方形面积def square(*args,**kwargs):return args[0] ** 2#计算圆形面积def circular(*args,**kwargs):return 3.14 * (args[0] ** 2)#判断参数if args[0].strip() == '长方形':return rectangle(args[1],args[2])elif args[0].strip() == '正方形':return square(args[1])elif args[0].strip() == '圆形':return circular(args[1])else:return '参数不正确!'ret1 = area('长方形',3,4)
ret2 = area('正方形',5)
ret3 = area('圆形',6)
print(ret1)
print(ret2)
print(ret3)

  

def area(*args):# 判断参数if args[0] == '长方形':def 计算长方形面积():s = args[1] * args[2]return sreturn 计算长方形面积()elif args[0] == '正方形':def 计算正方形面积():s = args[1] ** 2return sreturn 计算正方形面积()elif args[0] == '圆形':def 计算圆形面积():s = 3.14 * (args[1] ** 2)return sreturn 计算圆形面积()print(area('长方形', 2, 3))
print(area('正方形', 5))
print(area('圆形', 6))

给每个函数写一个记录日志的功能,
功能要求:每一次调用函数之前,要将函数名称,时间节点记录到log的日志中。
所需模块:
import time
struct_time = time.localtime()
print(time.strftime("%Y-%m-%d %H:%M:%S",struct_time))

#准备装饰器模版
def wrapper(f):def inner(*args,**kwargs):'''函数装饰前'''ret = f(*args,**kwargs)'''函数装饰之后'''return retreturn inner

  

import time
def wrapper(f):def inner(*args,**kwargs):'''被装饰函数之前'''ret = f(*args,**kwargs)'''被装饰函数之后'''struct_time = time.localtime()standard_time = time.localtime()print('函数名称:{} 时间节点:{}\n'.format(f.__name__, standard_time))return retreturn inner
@wrapper
def func1():'''此函数是测试的:return:'''print(666)time.sleep(0.3)return True
func1()

  加入些日志功能:

import time
def wrapper(f):def inner(*args,**kwargs):'''被装饰函数之前'''ret = f(*args,**kwargs)'''被装饰函数之后'''struct_time = time.localtime()standard_time = time.localtime()#写日志功能加入with open('function_log.txt', encoding='utf-8', mode='a+') as f1:f1.write('函数名称:{} 时间节点:{}\n'.format(f.__name__, standard_time))return retreturn inner
@wrapper
def func1():'''此函数是测试的:return:'''print(666)time.sleep(0.3)return True
func1()
def wrapper(func):def inner(*args,**kwargs):struct_time = time.localtime()time_now = time.strftime("%Y-%m-%d %H:%M:%S", struct_time)with open('log', encoding='utf-8', mode='a') as f1:f1.write('在时间是%s,执行了%s函数\n' % (time_now, func.__name__))ret = func(*args, **kwargs)'''函数执行之后操作'''return retreturn inner@wrapper
def func1():time.sleep(1)print(6666)
@wrapper
def func2():time.sleep(2)print(7777)
func1()
func2()

  

写函数,传入一个参数n,返回n的阶乘
例如: cal(7)

  

def func3(n):count = 1for i in range(n,0,-1):count = count * ireturn count
print(func3(7))

  执行后输出:

5040

 

编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 要求登录成功一次(三次机会),后续的函数都无需再输入用户名和密码

准备雏形:

def check_login(func): #检查登陆的装饰器def inner(*args,**kwargs):'''函数被装饰之前'''ret = func(*args,**kwargs)'''函数被装饰之后'''return retreturn innerdef index():print("welcome to index page")@check_login
def home(): #用户主页print("welcome to home page")@check_login
def bbs(): #bbs页面print("welcome to bbs page")

  

#全局变量,用户状态
dic = {'username':None,'status':False,
}
#错误次数
i = 0def wrapper(func):def inner(*args, **kwargs):#判断登录状态是否为Trueif dic['status']:#执行被装饰行函数ret = func(*args, **kwargs)return retelse:#这里需要修改全局变量,要global一下global iwhile i < 3:username = input('请输入用户名:').strip()password = input('请输入密码:').strip()with open('register_msg',encoding='utf-8') as f1:for j in f1:j_li = j.strip().split()  # ['张三','123']if username == j_li[0] and password == j_li[1]:#修改全局变量dic['username'] = usernamedic['status'] = Trueret = func(*args, **kwargs)return retelse:print('账号或者密码错误,请重新输入%s机会' % (2-i))i += 1return inner@wrapper
def article():print('文章')@wrapper
def diary():print('日记')@wrapper
def comment():print('评论')@wrapper
def file():print('文件')article()
diary()
comment()
file()

  

 

 

 

转载于:https://www.cnblogs.com/haowen980/p/8709844.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java学习总结 16个亮点

1.八大基本数据类型 byte(字节型8) int(整型;32;程序中一般默认为int型) short(短整型 16) long(长整型 32) float(浮点型 32) double(双精度浮点型 64) char(字符型 16) boolean(布尔型 只有true和false) 小范围内的整数类型可以通过赋值转化成大范围的数据类型.而大…

PHP聊天记录内啥,PHP的PSR系列轨范都有啥内容

PHP的PSR系列规范都有啥内容PSR是PHP Standard Recommendation的简写&#xff0c;它其实应该叫PSRs&#xff0c;即系列推荐标准&#xff1a;目前通过的规范有PSR-0(Autoloading Standard)、PSR-1(Basic Coding Standard)、PSR-2(Coding Style Guide)、PSR-3(Logger Interface)、…

选择排序法对数组进行排序

package selectionSort;import java.util.Arrays;public class Exam { //使用选择排序法对数组进行排序public static void main(String[] args) {int[] nums {23,3453,123,54,12,45,145,135,656,146,65};SelectionSort(nums);System.out.println(Arrays.toString(nums));}publ…

唐骏给李开复泼冷水:创业不可复制

东方企业家》十月刊刊登我主持的唐骏专栏&#xff0c;发表评创业热潮的冷思考。 题&#xff1a;创业是不可复制的 李开复从谷歌辞职&#xff0c;投身到创业热潮之中。很多媒体朋友问我&#xff0c;如何评价开复的辞职和创业?对此我一概未作回答。其实我很关注&#xff0c;也引…

爬取校园新闻首页的新闻

1. 用requests库和BeautifulSoup库&#xff0c;爬取校园新闻首页新闻的标题、链接、正文。 import requests from bs4 import BeautifulSoup url requests.get("http://news.gzcc.cn/html/xiaoyuanxinwen/")url.encoding "utf-8" soup BeautifulSoup(…

php服务划分,云计算提供的服务分为哪三个层次

三个层次&#xff1a;1、基础设施即服务(IaaS)&#xff0c;向云计算提供商的个人或组织提供虚拟化计算资源&#xff1b;2、平台即服务(PaaS)&#xff0c;为开发人员提供通过全球互联网构建应用程序和服务的平台&#xff1b;3、软件即服务((SaaS)&#xff0c;通过互联网提供按需…

如何做个人职业规划和年度计划

在做规划的同时&#xff0c;已经结合工作和个人自身情况思考调整个人的职业规划以及2012年自己的学习成长计划。持续了大约2个月的时间&#xff0c;已经整理出了2012年自己的目标和计划。总结一下&#xff0c;制定个人规划大致分为几个步骤&#xff1a; 一、认识自己。主要包括…

centos 7 快速安装nginx

输入指令 vim /etc/yum.repos.d/nginx.repo 输入以下内容 [nginx] namenginx repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgcheck0 enabled1 wq 进行保存 验证是否安装成功 安装 yum install nginx 启动nginx服务 nginx 测试是否启动成功 在linux输入你的IP地…

matlab colorbar采用对数,matlab colorbar的使用 | 學步園

1&#xff1a;請問matlab中畫多張圖如何使用同一範圍的colorbar?例如生成了圖1,2,3生成圖1時&#xff0c;使用temp1caxis;將圖1的z值的取值範圍(即colorbar的取值範圍)取出。生成圖2,3時使用caxis(temp1)命令將圖2,3的z值的取值範圍設為同1相同。然後對各個同使用colorbar命令…

BFS简单搜索--POJ 2243

这题就是简单的BFS搜索&#xff0c;刚刚转到C&#xff0c;还有很多库函数不熟悉&#xff0c;理解到BFS是一种奇妙的迭代法&#xff0c;其用的主要是队列的性质。 1 /*BFS简单搜索*/ 2 #include<iostream> 3 #include<queue> 4 #include<cstring> 5 6 using …

python_cookies

1.将cookies保存到变量中&#xff0c;然后打印cookie中的值 #coding:utf-8 #将cookies保存到变量中&#xff0c;然后打印cookie中的值 import urllib2 import cookielib #声明一个CookieJar对象实例保存cookie cookiecookielib.CookieJar() #利用urllib2库中的HTTPCookieProces…

php拖拽原理,JS拖拽效果及原理解析

这篇文章主要介绍了如何实现js拖拽效果及原理解析,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下元素拖拽分成3个步骤&#xff1a;按下鼠标&#xff0c;移动鼠标&#xff0c;松开鼠标。拖拽原理&#xff1a;按下…

jqGrid细节备注—pager文字的设置,更改默认的提交方式

默认的pager显示的文字&#xff0c;在英文版本下是如下 (file grid.locale-en.js): $.jgrid { defaults : { recordtext: "View {0} - {1} of {2}", emptyrecords: "No records to view", loadtext: "Loading...", pgtext : "Page {0} of …

浅谈拓扑排序

今天来讲讲拓扑排序 度娘告诉我 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序&#xff0c;是将G中所有顶点排成一个线性序列&#xff0c;使得图中任意一对顶点u和v&#xff0c;若边(u,v)∈E(G)&#xff0c;则u在线性序列中出现在v之前。通常&#xff0c;这样…

iOS开发笔记[18/50]:在Mac OS X Lion系统中访问~/Library目录都需要点技巧

Mac虚拟机升级为Lion系统了&#xff0c;在iPhone模拟机调试时经常想访问应用程序的Document目录看看里面发生的状况&#xff0c;但在Lion系统中却找不到~/Library/Application Support/iPhone Simulator文件夹了。原来需要在Finder中这个~/Library文件夹默认是隐藏的&#xff0…

makemid+matlab,《MATLAB基础》双语课

MATLAB双语教学视频第17讲MATLAB双语教学视频第18讲Summarizing DataIn this section...“Overview” on page 5-10“Measures of Location” on page 5-10“Measures of Scale” on page 5-11“Shape of a Distribution” on page 5-11OverviewMany MATLAB functions enable y…

素数对猜想之python3实现

题目 让我们定义d​n​​为&#xff1a;d​n​​p​n1​​−p​n​​&#xff0c;其中p​i​​是第i个素数。显然有d​1​​1&#xff0c;且对于n>1有d​n​​是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。 现给定任意正整数N(<)&#xff0c;请计算不超…

java 获取六个月账期,应收帐龄分析里面账期分析能不能改为0-30天?

怎样安装摄像头的驱动程序怎样安装摄像头的驱动程序注意&#xff1a;请不要在未安装摄像头的驱动程序前将PC摄像头插入计算机USB接口中&#xff1b;如果在没有安装驱动程序的情况下提前插上摄像头&#xff0c;当WINDOWS提示安装驱动程序时&#xff0c;请点击取消键并将其拨出&a…

ribbon源码(1) 概述

ribbon的核心功能是提供客户端在进行网络请求时负载均衡的能力。主要有以下几个模块&#xff1a; 负载均衡器模块 负载均衡器模块提供了负载均衡能力&#xff0c;详细参见ribbon源码之负载均衡器。 配置模块 配置模块管理ribbon的配置信息&#xff0c;ribbon各个模块都通过配置…

Linux软件安装解决方案

Linux软件安装解决方案 在linux中安装软件是一件并不算轻松的工作&#xff0c;有很多中解决方案供你选择&#xff0c;但需要的是你的一点点耐心与智慧&#xff01;下面我将就Linux中最常见的安装方式&#xff0c;由浅入深的逐一做简单介绍与说明&#xff0c;希望可以给您带来帮…