python之旅5【第五篇】
装饰器详解
函数刚开始不解析内部,只是放进内存
装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。
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【第五篇】的更多相关文章
- Python之路【第五篇】:面向对象及相关
Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...
- Python之路【第五篇】:面向对象和相关
Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...
- 【Python之旅】第六篇(七):开发简易主机批量管理工具
[Python之旅]第六篇(七):开发简易主机批量管理工具 python 软件开发 Paramiko模块 批量主机管理 摘要: 通过前面对Paramiko模块的学习与使用,以及Python中多线程与多 ...
- 【python游戏编程之旅】第五篇---嗷大喵爱吃鱼小游戏开发实例
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 我们一同在前几期的博客中已经学到了很多pygame的基本知识了,现在该做个小游戏实战一下了. 前几期博客链接 ...
- Python自动化 【第十五篇】:CSS、JavaScript 和 Dom介绍
本节内容 CSS javascript dom CSS position标签 fixed: 固定在页面的某个位置 relative + absolute: 相对定位 opacity:0.5 设置透明度 ...
- Python开发【第十五篇】:Web框架之Tornado
概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...
- Python之路【第五篇】: 函数、闭包、装饰器、迭代器、生成器
目录 函数补充进阶 函数对象 函数的嵌套 名称空间与作用域 闭包函数 函数之装饰器 函数之可迭代对象 函数之迭代器 函数之生成器 面向过程的程序设计思想 一.函数进阶之函数对象 1. 函数对象 秉承着 ...
- Python之路【第五篇】python基础 之初识函数(一)和文件管理
转载请注明出处http://www.cnblogs.com/wupeiqi/articles/5453708.html 函数 一.背景 ...
- Python之路【第五篇续】:面向对象编程二
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABgQAAALaCAIAAABxja8cAAAgAElEQVR4nOzd6X9Tdd74/+uv+f5uzF
- Python之路【第五篇】:面向对象编程
面向对象编程思维导向图
随机推荐
- .NET Core 中的路径问题
NET Core 应用程序相对于以前的.NET Framework 应用程序在启动运行的方式上有一定的差异,今天就来谈一谈这个获取应用程序启动路径的问题. 1.工作路径 WorkingDirector ...
- 读写分离子系统 - C# SQL分发子系统 - Entity Framework支持
A2D Framework增加了EF支持,加上原先支持ADO.NET: 支持EF方式 支持ADO.NET方式 这次来讲如何让Entity Framework变成nb的读写分离 1. 先设计EF模型, ...
- .Net Core 在 Linux-Centos上的部署实战教程(一)
pa我是在VS2017上写好项目然后来部署的,我的宗旨能截图就少BB 服务器系统: Asp.Net Core版本: 1.往服务器安装.net core 2.1 https://www.microsof ...
- 【IE11请求中止】 XMLHttpRequest: 网络错误 0x2ef3的意外出现
BUG现象 今天排查BUG遇到一个有趣的BUG,测试的截图显示 这个BUG只在IE11下出现. BUG原因 这个问题的原因是keep-alive机制引起. 当浏览器在向一个网址发起请求时,会建立一个t ...
- 使用 OpenSSL 创建私有 CA:3 用户证书
OpenSSL 创建私有 CA 三部曲:使用 OpenSSL 创建私有 CA:1 根证书使用 OpenSSL 创建私有 CA:2 中间证书使用 OpenSSL 创建私有 CA:3 用户证书 在前文&l ...
- 2017湘潭大学邀请赛G题(贪心+优先队列)
参考博客:http://www.cnblogs.com/chendl111/p/6891770.html 题目链接:https://www.icpc.camp/contests/4mYguiUR8k0 ...
- Java面试题详解四:==和equals的去别
一,功能 1.对于== 作用于基本数据类型的变量,比较的存储的值是否相等, 作用于引用类型的变量,比较的是其所指向的对象的地址是否相同(即是否是同一个对象) 2.对于equals Object的equ ...
- java 获取下一个字母(传大写返回大写,传小写返回小写)
public static String getNextUpEn(String en){ char lastE = 'a'; char st = en.toCharArray()[0]; if(Cha ...
- Oracle 不小心删除undo数据文件以及磁盘空间不足导致不能登录的解决办法
在一次测试中,由于导入的数据量过大导致事务一直提交失败因为磁盘空间不够用了,一检查发现是undo表空间不够用,于是重新创建了一个表空间,准备把之前的undo表空间删除,删除时却发现一直删不掉,因为它一 ...
- vue-resources&axios
vue-resource vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应. vue-resource特点: 体积小 vue-re ...