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之路【第五篇】:面向对象编程
面向对象编程思维导向图
随机推荐
- 吉特日化MES-日化行业原料仓库所见问题汇总
2018年工作主要面向的是日化行业,其中包括日化生产以及日化生产原料仓库,和以往接触到仓库有点不一样在于日化行业原料的特性问题,日化行业的原料基本以粉尘和液体为主. 1. 原料的形态上: 日化行业原料 ...
- ThinkPHP+JQuery实现文件的异步上传
前端代码 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...
- docker容器与宿主交互数据
1.查看容器 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cd6957191 ...
- java的instanceof关键字
java 中的instanceof 运算符是用来判断对象是否是 特定类或这个特定类的子类 的一个实例. 用法: result = object instanceof class 参数: Result: ...
- Hadoop生态的配置
网盘下载地址 链接: https://pan.baidu.com/s/19qWnP6LQ-cHVrvT0o1jTMg 密码: 44hs Hadoop伪分布式配置 Hadoop 可以在单节点上以伪分布 ...
- 一些iptables配置
第一条是封堵22,80,8080端口的输出,第二条是为该ip的80端口设置输出白名单,亲测有效:第三条是禁止所有UDP报文的输出 iptables -I OUTPUT -p tcp -m multip ...
- Python_内置函数之map()
map 会根据提供的函数对指定序列做映射. 代码如下: def square(x): return x ** 2 ret = map(square, [1, 2, 3, 4, 5]) # 计算列表各元 ...
- python生成个性二维码学习笔记
在linux环境下进行编码 1.先进家目录,自行创建Code文件夹 cd Code 2.下载MyQR库 sudo pip3 install MyQR 3.下载所需资源文件并解压 Code/ $ wge ...
- 3 The simple past
1 许多动词通过在原型之后添加-ed 构成一般过去式. 其他动词有不规则的过去式,使用一般过去式的时间词语出现在句首或者句尾 The company grew from 400 to 5,000 pe ...
- mybatis源码分析(四)---------------代理对象的生成
在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...