装饰器详解

函数刚开始不解析内部,只是放进内存

装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。

1 下面以一个函数开始,理解下面概念

 def  foo():
print 'foo' foo 是函数
foo() 是执行函数

2 看下面的一个函数执行过程

 def  f1(arg):
arg() def func():
print '' f1(func)

3 上面的理解之后,看下面一个函数执行过程

 def auth(func):
def wrapper():
print "before"
func()
return wrapper
def f1():
print "f1"
auth(f1)

4 接着上边的,如何执行内部的内容, 引入装饰器

还是上面的函数,换了执行方式

 def auth(func):
def wrapper():
print "before"
func()
return wrapper
def f1():
print "f1"
ret=auth(f1)
ret()

5 装饰器引入

 def auth(func):
def wrapper():
print "before"
func()
return wrapper @auth
def f1():
print "f1 @auth=>auth(f1)==>f1=auth(f1)=def wrapper():
print "before"
func()
接下来再执行f1()就相当于执行了wrapper()函数
主要过程是执行auth函数,被装饰的函数作为参数传入auth--auth(f1),auth函数的返回值,赋值给被装饰的函数的函数名,---f1=wrapper

6 装饰器含参数(一个参数)

 def auth(func):
def inner(arg):
print "before"
func(arg)
return inner
@auth
def f2(arg):
print "f2" ,arg
f2('test') 结果
before
f2 test

7 多个参数,动态参数

 def auth(func):
def inner(*args,**kwargs):
print "before"
func(*arg,**kwargs)
print 'after'
return inner @auth
def f2(*args,**kwargs):
print "f2" f2('1.1.1.1')

8 含有返回值的装饰器

 def auth1(func):
def inner(*arg,**kwargs):
print 'before'
temp = func(*arg,**kwargs)
print 'after'
return temp #inner函数有了返回值
return inner @auth1
def fetch_list(arg):
print "fetch_list"
server_list = [,,]
return server_list ret = fetch_list('test')
print ret 结果
before
fetch_list
after
[, , ]

9 装饰器实现登录验证

主要就是增加了一个login函数

 def login():
name = 'dicky'
if name == 'dicky1':
return True
else:
return False def auth3(func):
def inner(*args,**kwargs):
is_login = login()
if not is_login:
return "invild"
temp = func(*args,**kwargs)
return temp
return inner
@auth3
def fetch_list(arg):
print "fetch_list"
server_list = [,,]
return server_list
ret=fetch_list('test')
print ret 结果
invild

10 装饰器实现token验证,跟上面的login差不多

 def login1(key):
name = 'alex1'
local = 'afcadfsgdgwegsfbdfgsgsfwe'
if local == key:
return True
else:
return False
def auth3(func):
def inner(*arg,**kwargs):
# key=kwargs['token']
# del kwargs['token']
key = kwargs.pop('token') #删除多传入的参数
is_login = login1(key)
if not is_login:
return "invild"
print 'before'
temp = func(*arg,**kwargs) #上面删除了多传入的参数,这里就不会报错了
print 'after'
return temp
return inner @auth3
def fetch_list(arg):
print "fetch_list"
server_list = [,,]
return server_list key = 'afcadfsgdgwegsfbdfgsgsfwe'
ret = fetch_list('test',token=key)
print "llllllllll"
print ret

11 多装饰器

先执行外部装饰器,然后在执行内部装饰器

 def w1(func):
def inner():
print 'w1 before'
func()
print 'w1 after'
return inner
def w2(func):
def inner():
print 'w2 after'
func()
print 'w2 after'
return inner
@w2
@w1
def foo():
print 'foo' foo()
结果
w2 after
w1 before
foo
w1 after
w2 after

12 装饰器附加参数

 def Before(request,kargs):
print 'before' def After(request,kargs):
print 'after' def Filter(before_func,after_func):
def outer(main_func):
def wrapper(request,kargs): before_result = before_func(request,kargs)
if(before_result != None):
return before_result; main_result = main_func(request,kargs)
if(main_result != None):
return main_result; after_result = after_func(request,kargs)
if(after_result != None):
return after_result; return wrapper
return outer @Filter(Before, After)
def Index(request,kargs):
print 'index'

过程如下

 @Filter(Before, After)

先执行Filter(Before, After)函数,获取返回值ret,获取返回值后,拼接成@ret,也就是相当于引入了两个参数,以至于后来可以使用这两个参数。

13 functools.wraps 的作用

上述的装饰器虽然已经完成了其应有的功能,即:装饰器内的函数代指了原函数,注意其只是代指而非相等,原函数的元信息没有被赋值到装饰器函数内部。例如:函数的注释信息

看下面的两个例子

def outer(func):
def inner(*args, **kwargs):
print(inner.__doc__) # None
return func()
return inner @outer
def function():
"""
asdfasd
:return:
"""
print('func') function()
结果
None #并没有输出__doc__的信息

加上@functools.wraps之后

  import functools
1 def outer(func):
@functools.wraps(func)
def inner(*args, **kwargs):
print(inner.__doc__) # None
return func()
return inner @outer
def function():
"""
asdfasd
:return:
"""
print('func') function()
结果
asdfasd
:return: func #输出了原函数的__doc__内容

二 递归

1 编写数列

 斐波那契数列指的是这样一个数列 , , , , , , , , , , , , , ,,,,,,,,,,,

函数如下

 def  func(arg1,arg2):
if arg1==:
print arg1,arg2
arg3=arg1+arg2
print arg3
func(arg2,arg3) func(,)

2 递归的返回值

先看下面的一个简单例子

 def n5():
return ''
def n4():
n5()
def n3():
n4()
def n2():
n3()
def n1():
n2()
ret=n1()
print ret 结果None

分析如下

上面的函数首先执行
n1()---n2()--n3()---n4()--n5()
到执行到n5的时候有返回值,n5函数的返回值返回给调用n5函数的函数n4
即res=n5()----def n4(): 但是n4没有返回值,n3也没有返回值,n2也没有返回值,n1也没有返回值,所以最后返回none
改进一下,让他有返回值

 def n5():
return ''
def n4():
return n5()
def n3():
return n4()
def n2():
return n3()
def n1():
return n2()
ret=n1()
print ret 结果 这样让它每次都有返回值

3 看下面的递归例子(改进了一下上边的数列例子)

 def  func(arg1,arg2):
if arg1==:
print arg1,arg2
arg3=arg1+arg2
if arg3>:
return arg3
func(arg2,arg3) ret = func(,)
print ret 结果为None

分析如下

执行第一次func(0,1)没有返回值
执行第二次func(1,1)也没有返回值
..........
当执行到func(610,987)的时候,接着执行上面,arg=1597,满足条件,return返回1597,谁调用的返回给谁,也就是返回给func(610,987),但是在这之前执行func()函数却没有返回值,跟上面的例子差不多,所以最后返回None

改进之后:

 def  func(arg1,arg2):
if arg1==:
print arg1,arg2
arg3=arg1+arg2
if arg3>:
return arg3
return func(arg2,arg3) ret = func(,)
print ret 结果

三模块

模块分为三种:

  • 自定义模块
  • 内置模块
  • 开源模块

自定义模块

1

2

导入模块

 import module
from module.xx.xx import xx
from module.xx.xx import xx as rename
from module.xx.xx import *

导入模块其实就是告诉Python解释器去解释那个py文件

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 __init__.py 文件
 模块路径
import sys
print sys.path
结果
['F:\\untitled5\\test', 'F:\\untitled5', 'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\DLLs', 'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win', 'C:\\Python27\\lib\\lib-tk', 'C:\\Python27', 'C:\\Python27\\lib\\site-packages', 'C:\\Python27\\lib\\site-packages\\pip-9.0.1-py2.7.egg']

常用内置模块

os模块

 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

sys模块

 sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit()
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称

python之旅5【第五篇】的更多相关文章

  1. Python之路【第五篇】:面向对象及相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

  2. Python之路【第五篇】:面向对象和相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

  3. 【Python之旅】第六篇(七):开发简易主机批量管理工具

    [Python之旅]第六篇(七):开发简易主机批量管理工具 python 软件开发 Paramiko模块 批量主机管理 摘要: 通过前面对Paramiko模块的学习与使用,以及Python中多线程与多 ...

  4. 【python游戏编程之旅】第五篇---嗷大喵爱吃鱼小游戏开发实例

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 我们一同在前几期的博客中已经学到了很多pygame的基本知识了,现在该做个小游戏实战一下了. 前几期博客链接 ...

  5. Python自动化 【第十五篇】:CSS、JavaScript 和 Dom介绍

    本节内容 CSS javascript dom CSS position标签 fixed: 固定在页面的某个位置 relative + absolute: 相对定位 opacity:0.5 设置透明度 ...

  6. Python开发【第十五篇】:Web框架之Tornado

    概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...

  7. Python之路【第五篇】: 函数、闭包、装饰器、迭代器、生成器

    目录 函数补充进阶 函数对象 函数的嵌套 名称空间与作用域 闭包函数 函数之装饰器 函数之可迭代对象 函数之迭代器 函数之生成器 面向过程的程序设计思想 一.函数进阶之函数对象 1. 函数对象 秉承着 ...

  8. Python之路【第五篇】python基础 之初识函数(一)和文件管理

    转载请注明出处http://www.cnblogs.com/wupeiqi/articles/5453708.html 函数 一.背景                                 ...

  9. Python之路【第五篇续】:面向对象编程二

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABgQAAALaCAIAAABxja8cAAAgAElEQVR4nOzd6X9Tdd74/+uv+f5uzF

  10. Python之路【第五篇】:面向对象编程

    面向对象编程思维导向图

随机推荐

  1. wpf、winform仿QQ靠边隐藏

    先说下下面的代码和demo是wpf的,如果winform要用,改动不大的. 实现思路: 通过定时刷新鼠标位置 和 窗体坐标 进行计算 来控制窗体的隐藏 显示 代码都有详细的注释 //窗体状态 true ...

  2. Java线程池实现原理与技术(ThreadPoolExecutor、Executors)

    本文将通过实现一个简易的线程池理解线程池的原理,以及介绍JDK中自带的线程池ThreadPoolExecutor和Executor框架. 1.无限制线程的缺陷 多线程的软件设计方法确实可以最大限度地发 ...

  3. 升级NGINX支持HTTP/2服务端推送

    内容概览 NGINX从1.13.9版本开始支持HTTP/2服务端推送,上周找时间升级了下NGINX,在博客上试验新的特性. 升级工作主要包括: 升级NGINX 修改NGINX配置 修改wordpres ...

  4. Python_列表推导式_生成器的表达式_各种推导式_40

    列表推导式: #列表推导式: egg_list = [] for i in range(10): egg_list.append('鸡蛋%s'%i) print(egg_list) egon egg_ ...

  5. 使用Vue自己做一个简单的MarkDown在线编辑器

    1.首先要下载mark组件. npm install marked --save 2.在Vcontent.vue中简单写一些样式. <template> <div class=&qu ...

  6. 【学习总结】Git学习-参考廖雪峰老师教程六-分支管理

    学习总结之Git学习-总 目录: 一.Git简介 二.安装Git 三.创建版本库 四.时光机穿梭 五.远程仓库 六.分支管理 七.标签管理 八.使用GitHub 九.使用码云 十.自定义Git 期末总 ...

  7. php之常用扩展总结

    在此总结,开发中经常使用到的扩展,来进行日常PHP的开发工作 bcmath(精确数值处理) bz2 calendar Core ctype curl date dom ereg exif filein ...

  8. Java 线程的创建和启动

    Java 使用 Thread 类代表线程,所有的线程对象都必须是 Thread 类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码). Java 使用线程执 ...

  9. drf开发中常见问题

    开发常见问题及解决 问题: 一.本地系统不能重现的bug 二.api接口出错不能及时的发现或难找到错误栈 三.api文档管理问题 四.大量的url配置造成url配置越来越多难以维护 五.接口不及时去更 ...

  10. C# 中那些常用的工具类(Utility Class)(三)

    今天来接着写这个系列的文章,这一篇主要是用来介绍关于C#中的XML序列化的问题,这个相信大家一定会经常使用它,特别是在WPF中,有时候我们需要将我们后台的数据保存在数据库中,从而在软件下一次启动的时候 ...