Python学习 day12
一、@wraps
__name__ 查看函数的名字
__doc__ 查看函数的文档字符串
例:
def func(arg):
"""
这是一个测试函数,这里是函数说明
:param arg: 参数说明
:return: 返回值说明
"""
return arg print(func.__name__)
print(func.__doc__)
结果:

但是,经过装饰器装饰的函数,我们知道虽然调用与原来一致,但原函数名实际指向的却是装饰器中的inner函数,所以在调用__name__和__doc__时,得到的结果,如下:
def wrapper(func):
def inner(*args, **kwargs):
"""
这是一个装饰器内部函数,对原函数进行装饰
:param args: 原函数中的位置传参
:param kwargs: 原函数中的按关键字传参
:return: 返回原函数执行后的结果
"""
print("在原函数之前")
ret = func(*args, **kwargs)
print("在原函数之后")
return ret
return inner @wrapper
def test(arg):
"""
这是一个测试函数,这里是函数说明
:param arg: 参数说明
:return: 返回值说明
"""
return arg print(test.__name__)
print(test.__doc__)
结果:

可以看到,被装饰的函数调用__name__和__doc__得到的不再是原函数的名称和文档字符串
为了解决这个问题,我们引入wraps装饰inner函数,就可以正常获取元函数的函数名和文档字符串了,如下:
from functools import wraps def wrapper(func):
@wraps(func) # 用wraps装饰inner函数
def inner(*args, **kwargs):
"""
这是一个装饰器内部函数,对原函数进行装饰
:param args: 原函数中的位置传参
:param kwargs: 原函数中的按关键字传参
:return: 返回原函数执行后的结果
"""
print("在原函数之前")
ret = func(*args, **kwargs)
print("在原函数之后")
return ret
return inner @wrapper
def test(arg):
"""
这是一个测试函数,这里是函数说明
:param arg: 参数说明
:return: 返回值说明
"""
return arg print(test.__name__)
print(test.__doc__)
执行以上代码,得到:

二、带参数的装饰器
在有些情况下,需要使用带参数的装饰器,把外部的变量值传入装饰器中,进行相关操作。
举例:如有一种情况,项目经理需要测试每个人设计的函数的执行时间,以此来对每个人的函数进行评测,这时就需要增加函数执行的计时功能,需要用到装饰器。在评测结束后,项目经理又要求将计时功能去掉,这如果把装饰器再一个个去除就会非常麻烦,因此需要一种变通的方法能保证需要的时候增加装饰器,不需要时去掉。
就这个例子设计一个装饰器,我们有如下方法:
import time FLAG = True # 标志位 def timmer_out(FLAG):
def timmer(func):
def inner(*args, **kwargs):
if FLAG: # FLAG为True时,增加计时功能
start = time.time()
ret = func(*args, **kwargs)
end = time.time()
print(end - start)
return ret
else: # False时不装饰
return func(*args, **kwargs)
return inner
return timmer def func1():
print("执行func1")
time.sleep(3)
print("func1结束") @timmer_out(FLAG) # 语法糖,实际如下面func1
def func2():
print("执行func2")
time.sleep(5)
print("func2结束") t = timmer_out(FLAG)
func1 = t(func1)
func1()
func2()
结果:

若FLAG=False,结果:

可以看到,通过控制FLAG的值就可以控制是否给原函数增加装饰,解决了问题。
其实timmer_out函数就做了一个利用闭包传参的功能,若没有timmer_out这个外部函数,里面inner想使用全局变量FLAG的值在python中也是可以的,但这样的用法不是程序设计推荐的,不如由外部函数timmer_out传入更规范。
三、多个装饰器装饰一个函数
多个装饰器装饰一个函数依然类似java中的过滤器和拦截器,与aop思想一致,因多个装饰器都对函数有增加功能,那执行的顺序是什么呢,如:
def wrapper1(func):
def inner(*args, **kwargs):
print("-------wrapper1在函数调用前--------")
ret = func(*args, **kwargs)
print("-------wrapper1在函数调用后--------")
return ret
return inner def wrapper2(func):
def inner(*args, **kwargs):
print("-------wrapper2在函数调用前--------")
ret = func(*args, **kwargs)
print("-------wrapper2在函数调用后--------")
return ret
return inner def wrapper3(func):
def inner(*args, **kwargs):
print("-------wrapper3在函数调用前--------")
ret = func(*args, **kwargs)
print("-------wrapper3在函数调用后--------")
return ret
return inner @wrapper2
@wrapper1
@wrapper3
def func():
print("我是被装饰函数") func()
结果:

可看到,装饰器的执行顺序是根据装饰顺序来的:2-1-3-func-3-1-2
四、零散知识点
1、函数的注释
在python中写的函数,也有函数注释,类似java的方法注释,用于说明函数的主要功能,参数和返回值。
具体写法:
def func(arg):
"""
这是一个测试函数,这里是函数说明
:param arg: 参数说明
:return: 返回值说明
"""
return arg
在pycharm中函数下面直接输入三个”工具会自动显示函数注释的内容
2、os.path.getsize()
从os模块引入getsize()函数,用于判断文件大小。例:
import os
print(os.path.getsize('test')) # 获取test文件的大小,单位byte
五、其他
课程老师推荐了两本书《Python核心编程》、《流畅的python》,可以买来看看。
Python学习 day12的更多相关文章
- python学习Day12 函数的默认值、三元表达式、函数对象(函数名)的应用场景、名称空间与作用域
复习 1.字符串的比较: -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较 2. 函数的参数 : 1)实参与形参: -- 形参:在函数定义时()中出现的参数 ...
- python学习-day12:列表、元祖、字典介绍和内置
list:列表 >>>----可以被修改.修改成元素,元素可以使单独的数字,也可以是:新的list. 通过:链表..每个元素存储的时候,同时会指向下一个元素. 二.list编辑修改方 ...
- python学习day12
目录 html结构与标签 css样式 html结构之head <head> 标签用于定义文档的头部,它是所有头部元素的容器.<head> 中的元素可以引用脚本.指示浏览器在 ...
- python学习day12 函数Ⅳ (闭包&内置模块)
函数Ⅳ (闭包&内置模块) 1.内置函数(补充) lambda表达式也叫匿名函数. 函数与函数之间的数据互不影响,每次运行函数都会开一个辟新的内存. item = 10 def func(): ...
- python学习 day12 (3月18日)----(装饰器内置函数)
读时间函数: # import time # def func(): # start_time = time.time() # 代码运行之前的时间 # print('这是一个func函数') # ti ...
- Python学习-day12 Mysql
MYSQ数据库的安装使用 Linux/UNIX上安装Mysql Linux平台上推荐使用RPM包来安装Mysql,MySQL AB提供了以下RPM包的下载地址: MySQL - MySQL服务器.你需 ...
- python学习(day1-2)
python 学习(day - 1-2 ) 变量:将运算的中间结果暂存到内存,以便后续程序调⽤. 变量的命名规则: 1, 变量由字⺟, 数字,下划线搭配组合⽽成 2, 不可以⽤数字开头,更不能是全数字 ...
- python学习博客地址集合。。。
python学习博客地址集合... 老师讲课博客目录 http://www.bootcdn.cn/bootstrap/ bootstrap cdn在线地址 http://www.cnblogs. ...
- 【目录】Python学习笔记
目录:Python学习笔记 目标:坚持每天学习,每周一篇博文 1. Python学习笔记 - day1 - 概述及安装 2.Python学习笔记 - day2 - PyCharm的基本使用 3.Pyt ...
随机推荐
- [GO]匿名函数和defer
package main import "fmt" func main() { a := 10 b := 20 defer func() { fmt.Printf("a ...
- ubuntu 16.04快速建lvm
1.准备2块虚拟硬盘 在执行下面之前先安装:lvm和mkfs.xfs apt install lvm2 -y apt install xfsprogs dd if=/dev/zero of=ceph- ...
- ngix 创建新的网站
1. 进入ngix 的目录的conf 目录 的 vhosts 2. 复制一份新的v2.edc.com.conf 3. server_name : v2.edc.com root : /ali/... ...
- Android view状态保存
为什么我们需要保存View的状态? 这个问题问的好!我坚信移动应用应该帮助你解决问题,而不是制造问题. 想象一下一个非常复杂的设置页面: 这并不是从一个移动应用的截图(这不是典型的win32程序吗.. ...
- web项目不能链接数据库
mysql的root没有权限 例如,你想root使用123456从任何主机连接到mysql服务器. 1 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@' ...
- Linq研究
微软在.NET 3.5中加入了LINQ技术,作为配套改进了C#语言,加入了Lambda表达式,扩展方法,匿名类型等新特性用以支持LINQ.微软同时提出了要使用声明式编程,即描述计算规则,而不是描述计算 ...
- C++三种野指针及应对/内存泄露
C++三种野指针及应对/内存泄露 野指针,也就是指向不可用内存区域的指针.如果对野指针进行操作,将会使程序发生不可预知的错误,甚至可能直接引起崩溃. 野指针不是NULL指针,是指 ...
- C#成员设计建议
所谓成员,是指类型的字段和方法.在成员设计时,掌握一定原则可以避免设计上的陷阱. 1.不要为抽象类提供公开的构造方法 抽象类可以有构造方法,但是抽象类不能实例化.如果编程人员没有制定构造方法,编译器会 ...
- 读取二元组列表,打印目录的层级结构-----C++算法实现
要求是--某个文件中存储了一个最多3层的层级结构,其中每个元素都是一个自然数,它的存储方法是一个二元组的列表,每个二元组的形式为:(元素,父元素).现在希望能够通过读取该二元组列表,打印出目录的层级结 ...
- SSL证书可以给多个域名使用吗?
欢迎访问网易云社区,了解更多网易技术产品运营经验 从信任等级的角度来说,SSL证书主要分为三类: 1.域名型https证书(DVSSL):信任等级一般,只需验证网站的真实性便可颁发证书保护网站: 2. ...