装饰器详解

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

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

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. Groovy语言学习--语法基础(5)

    至此groovy语言学习-语法基础就结束了,新的工作已经安排下来,要干活了. 对groovy了解到一定程度之后就可以在java项目中对其进行引入了.为此新建了一个微型的项目,个人觉得千言万语不如代码实 ...

  2. 波音,自动驾驶bug未修复,致346人丧生!5个月内两次坠毁!其中,包括8名中国公民

    一,波音737 MAX再次坠毁 继2018年10月29日,印尼波音737MAX飞机坠入爪哇海,导致178名乘客不幸遇难后,时隔不足5月,上周日,埃塞俄比亚航空公司一架波音737MAX客机在飞往肯尼亚途 ...

  3. 朱晔和你聊Spring系列S1E4:灵活但不算好用的Spring MVC

    阅读PDF版本 本文会以一些例子来展现Spring MVC的常见功能和一些扩展点,然后我们来讨论一下Spring MVC好用不好用. 使用SpringBoot快速开始 基于之前的parent模块,我们 ...

  4. Jmeter实例(二)简单的性能测试场景

    我们在性能测试过程中,首先应该去设计测试场景,模拟真实业务发生的情境,然后针对这些场景去设计测试脚本.为了暴露出性能问题,要尽可能的去模拟被测对象可能存在瓶颈的测试场景. 我在本地部署了一个项目,可以 ...

  5. Truncated Power Method for Sparse Eigenvalue Problems

    目录 算法 k的选择 \(x\)的初始化 代码 抱歉,真的没怎么看懂,当然,估计和我现在没法静下心来好好看也有关系. 算法 想法非常非常简单吧,就是在原来幂法的基础上,每次迭代的时候再加个截断.当然, ...

  6. gin框架学习手册

    前言 gin框架是go语言的一个框架,框架的github地址是:https://github.com/gin-gonic/gin 转载本文,请标注原文地址:https://www.cnblogs.co ...

  7. ipython安装( jupyter)

    生产环境:win10 64位 pip的版本不是最新的,输入命令 python -m pip install --upgrade pip 更新我们的pip,pip不是最新的也会导致安装不了ipython ...

  8. 生命周期函数以及vue的全局注册

    beforeCreate 在创造实例之前 created 创造实例以后 beforeMount 在挂载前 render 渲染节点到页面上 //将虚拟dom数组渲染出来 mounted 挂载以后 bef ...

  9. [转帖]Stack的三种含义

    Stack的三种含义 http://www.ruanyifeng.com/blog/2013/11/stack.html 学习编程的时候,经常会看到stack这个词,它的中文名字叫做"栈&q ...

  10. spring IOC源码分析(ApplicationContext)

    在上一篇文章中,我们以BeanFactory这条主线进行IOC的源码解析的,这里,将以ApplicationContext这条线进行分析.先看使用方法: @Test public void testA ...