一、@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. [GO]面向对象和面对过程的方式

    package main import ( "fmt" ) //这里为面向过程的方式 func Add(a, b int) int { return a + b } //面向对象, ...

  2. QT学习之事件处理

    Qt事件机制 Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.. Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. Qt事件的类型很多, 常见的qt的事件如下: 键盘事 ...

  3. 前端福利之改变placeholder颜色的方法(转)

    之前拿到一个设计图,Placeholder是白色的,所以就查看了一下改变placeholder的方法: input::-webkit-input-placeholder { /* WebKit bro ...

  4. 在 CentOS 上部署 Nginx 环境

    这里的案例主要通过虚拟机( vmware workstation (14) )的方式安装 Center OS 到本地环境 资源下载:  vmware workstation   / CentOS 本次 ...

  5. C# 判断是否是在设计模式下有效的方法

    public static bool IsDesignMode() { bool returnFlag = false; #if DEBUG if (LicenseManager.UsageMode ...

  6. 8) Struts2 2 SpringMVC

    git@github.com:witaste/smse.git 数据库脚本: /* Navicat MySQL Data Transfer Source Server : 新服务器 Source Se ...

  7. SVN客户端--TortoiseSVN使用说明【转】

    TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理. TortoiseS ...

  8. mysql中四种存储引擎的区别和选择

    前言 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据.不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能,使用不同的存储引擎,还可以 ...

  9. 洛谷 4051 [JSOI2007]字符加密(后缀数组)

    题目描述 喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法. 例如‘JSOI07’,可以读作 ...

  10. Servlet 学习总结-1

    JavaWeb应用程序中所有的请求-响应都是由Servlet来完成的.Servlet是Java Web的核心程序,所有的网址(请求-响应)都交给Servlet来处理. Servlet在Web应用中被映 ...