一、@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的更多相关文章

  1. python学习Day12 函数的默认值、三元表达式、函数对象(函数名)的应用场景、名称空间与作用域

    复习 1.字符串的比较: -- 按照从左往右比较每一个字符,通过字符对应的ascii进行比较 2. 函数的参数 : 1)实参与形参:       -- 形参:在函数定义时()中出现的参数       ...

  2. python学习-day12:列表、元祖、字典介绍和内置

    list:列表 >>>----可以被修改.修改成元素,元素可以使单独的数字,也可以是:新的list. 通过:链表..每个元素存储的时候,同时会指向下一个元素. 二.list编辑修改方 ...

  3. python学习day12

    目录 html结构与标签 css样式   html结构之head <head> 标签用于定义文档的头部,它是所有头部元素的容器.<head> 中的元素可以引用脚本.指示浏览器在 ...

  4. python学习day12 函数Ⅳ (闭包&内置模块)

    函数Ⅳ (闭包&内置模块) 1.内置函数(补充) lambda表达式也叫匿名函数. 函数与函数之间的数据互不影响,每次运行函数都会开一个辟新的内存. item = 10 def func(): ...

  5. python学习 day12 (3月18日)----(装饰器内置函数)

    读时间函数: # import time # def func(): # start_time = time.time() # 代码运行之前的时间 # print('这是一个func函数') # ti ...

  6. Python学习-day12 Mysql

    MYSQ数据库的安装使用 Linux/UNIX上安装Mysql Linux平台上推荐使用RPM包来安装Mysql,MySQL AB提供了以下RPM包的下载地址: MySQL - MySQL服务器.你需 ...

  7. python学习(day1-2)

    python 学习(day - 1-2 ) 变量:将运算的中间结果暂存到内存,以便后续程序调⽤. 变量的命名规则: 1, 变量由字⺟, 数字,下划线搭配组合⽽成 2, 不可以⽤数字开头,更不能是全数字 ...

  8. python学习博客地址集合。。。

    python学习博客地址集合...   老师讲课博客目录 http://www.bootcdn.cn/bootstrap/  bootstrap cdn在线地址 http://www.cnblogs. ...

  9. 【目录】Python学习笔记

    目录:Python学习笔记 目标:坚持每天学习,每周一篇博文 1. Python学习笔记 - day1 - 概述及安装 2.Python学习笔记 - day2 - PyCharm的基本使用 3.Pyt ...

随机推荐

  1. 【转载】实战mysql分区(PARTITION)

    转载地址:http://lobert.iteye.com/blog/1955841 前些天拿到一个表,将近有4000w数据,没有任何索引,主键.(建这表的绝对是个人才) 这是一个日志表,记录了游戏中物 ...

  2. Tomcat 开机自启动

    一.安装JDK和Tomcat 1,安装JDK:直接运行jdk-7-windows-i586.exe可执行程序,默认安装即可. 备注:路径可以其他盘符,不建议路径包含中文名及特殊符号. 2.安装Tomc ...

  3. Hadoop的Windows伪分布式学习

    解压hadoop-2.7.2.zip,不是tar.gz,前者是Windows所用的 解压到路径,设置环境变量 HADOOP_HOME=E:\hadoop-2.7.2\ HADOOP_USER_HOME ...

  4. Mac OS X Yosemite & Arduino安装CH340 USB转串口驱动

    新买的Arduino开发板 USB转串口使用了CH340芯片,在Mac OS X Yosemite上正常安装驱动后,在Arduino IDE的端口没发现相应的设备,使用以下方法后就能使用USB转串口调 ...

  5. [LeetCode 题解]:Swap Nodes in Pairs

    前言   [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html   1.题目描述 Given a li ...

  6. EF的使用

    Expression<Func<CustomerType, bool>> expression = c => (c.Id != null); var c = from u ...

  7. Huawei .V3 Extention audio Play

    相关dll下载 链接 using System;using System.IO;using System.Threading;using Alvas.Audio;using NAudio.Wave; ...

  8. performance checklist

    - embree integration                                       0w - uncompressed bvh nodes               ...

  9. Echart自定义y轴刻度信息2

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. java内存模型(jMM)(二)

    volatile关键字 volatile是一个类型修饰符(type specifier),就像大家更熟悉的const一样,它是被设计用来修饰被不同线程访问和修改的变量.volatile的作用是作为指令 ...