一、@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. linux 创建数据库

    mysql -uroot -pxxxxxx 1. 修改服务器的字符集 打开/etc/mysql/my.cnf,在[mysqld]后添加character-set-server=utf8 2. 查看my ...

  2. gitlab 升级到 5.3 之后不能pull

    升级gitlab到5.3之后pull出现下面的错误: /usr/local/lib/ruby/1.9.1/net/protocol.rb:146:in `rescue in rbuf_fill': T ...

  3. ENVI 图像特征提取

  4. 编写高质量代码改善C#程序的157个建议——建议71:区分异步和多线程应用场景

    建议71:区分异步和多线程应用场景 初学者有时候会将异步和多线程混为一谈.如果对它们之间的区别不是很清楚,很容易写出下面这样的代码: private void buttonGetPage_Click( ...

  5. Appium常用Api实操

    本文是基于python语言在android上实操的,仅记录(忽略排版~~~) 会不时更新的: from appium import webdriver from selenium.webdriver. ...

  6. 【转载】UML类图几种关系的总结

    因为有的时候很久不弄UML图,老是忘记几个常见的连接线的意思,这篇完全说转载:UML类图几种关系的总结 在UML类图中,常见的有以下几种关系: 泛化(Generalization),  实现(Real ...

  7. ViewController关闭自身返回前一个View

    点击按钮号响应的函数 @IBAction func onBack(sender : AnyObject) { self.dismissViewControllerAnimated(true, comp ...

  8. dom4j学习总结(一)

    dom4j学习总结(一) (一)创建Document的基本操作 /**  * xml基本操作  */ public void BaseOperation(){  //创建一个document  Doc ...

  9. MySQL不带where条件的UPDATE和DELETE 限制操作说明

    本文来自 网易云社区 . 数据安全是业务的基石,但是DBA 总会遇到救火情况,业务误删除全表或者误更新错全表业务数据,导致服务不可用 sql_safe_updates参数可以限制不带where条件的u ...

  10. React Native 搭建开发环境

    1.先安装node.js,https://nodejs.org/en/download/ 然后,双击下载好的.msi文件安装即可,安装完成后,打开终端,输出npm -v 即可查看我们刚才安装的node ...