Python-装饰器详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python-装饰器详解相关的知识,希望对你有一定的参考价值。
初学python,装饰器是什么玩意儿?
1:装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。
2:至少两层函数
方式一: 理解方式
def auth(func): def inner(): print ‘before‘ func() return inner def f1(): print ‘f1‘ ret = auth(f1) f1 = ret f1()
执行结果:
before
f1
执行过程:
# 1:执行def auth(func): # 2: def f1(): # 3: ret = auth(f1) 执行auth函数,将f1传值给func, # 因为没有执行inner函数,所以return直接返回,但是返回的是inner函数名,里面的func==传入的f1 # 4: 此时 ret = innet函数名 # 5:执行f1 = ret,将inner函数名赋值给f1 # 5:执行f1(),也就是执行inner函数,然后打印before,它里面的func函数,但是func==f1,所以执行f1函数,打印f1
方式二:正常方式
def auth(func): def inner(): print ‘before‘ func() return inner @auth def f1(): print ‘f1‘ f1()
执行过程:
# 1:使用@auth来代替注释掉的两行。 # 2:执行@auth,将下面的函数名f1作为auth的参数 # 3:执行auth函数,被装饰的函数作为参数auth(foo),auth函数的返回值,赋值给被装饰的函数的函数名@auth
方式三:在函数执行前、后分别做操作
def auth(func): def inner(): print ‘before‘ func() print ‘after‘ return inner @auth def f1(): print ‘f1‘ f1() 结果: before f1 after
方式四:带参数的装饰器
def auth(func): def inner(arg): print ‘验证‘ func(arg) print ‘日志‘ return inner @auth def f1(arg): print ‘f1‘,arg f1(‘带参数‘) 结果: 验证 f1 带参数 日志
方式五:含有return返回值
def auth(func): def inner(*args,**kwargs): print ‘验证‘ tmp = func(*args,**kwargs) print ‘登陆日志‘ return tmp return inner @auth def fetch_server_list(): print ‘server list‘ server_list = [1,2,3,4,5] return server_list ret = fetch_server_list() print ret 结果: 验证 server list 登陆日志 [1, 2, 3, 4, 5]
方式六:多个不同类型的参数。
def login(): name = ‘ccc‘ if name == ‘cgt‘: return True else: return False def auth(func): def inner(*args,**kwargs): is_login = login() if not is_login: return ‘invaild username‘ tmp = func(*args,**kwargs) print ‘登陆日志‘ return tmp return inner @auth def fetch_server_list(): print ‘server list‘ server_list = [1,2,3,4,5] return server_list ret = fetch_server_list() print ret 结果:1:如果name = ccc 则输出 invaild username 2:如果name = cgt 则输出 server list 登陆日志 [1, 2, 3, 4, 5]
方式七:举例验证功能,使用Key值
功能函数
def login(key): local = "1234567890" if key == local: return True else: return False def auth(func): def inner(*args,**kwargs): key = kwargs.pop(‘token‘) #token是从调用函数是传参进来的
is_login = login(key) if not is_login: return ‘invaild username‘ tmp = func(*args,**kwargs) print "登陆日志" return tmp return inner @auth def fetch_server_list(arg): print ‘server list‘ server_list = [1,2,3,4,5,6] return server_list
调用函数
import tmp key = "1234567890" #key = "12345678" ret = tmp.fetch_server_list(‘text‘,token=key) print ret
执行结果:1:如果两者的key相同;则正确执行结果是: server list
登陆日志
[1, 2, 3, 4, 5, 6]2:如果key不同,则输出invaild username
方式八:多装饰器
def w1(func): def inner(): print ‘before--1‘ func() print ‘after--1‘ return inner def w2(func): def inner(): print ‘before--2‘ func() print ‘after--2‘ return inner @w2 @w1 def f1(): print ‘1111‘ f1() 结果: before--2
before--1 1111
after--1
after--2
递归
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368
实现方式:
def func(arg1,arg2): if arg1 == 0: pass arg3 = arg1 + arg2 print arg3 func(arg2,arg3) func(0,1)
如果数值大约1000,就返回这个数字
def func(arg1,arg2): if arg1 == 0: pass arg3 = arg1 + arg2 if arg3 > 1000: return arg3 ret = func(arg2,arg3) return ret print func(0,1)
模块
模块是用一块代码实现某个功能的代码的集合
例如:os是系统相关的模块;file是文件操作相关的模块
模块的种类
- 自定义模块
- 内置模块
- 开源模块
自定义模块
1:定义模块
自己编写的实现某个功能的.py文件,就称之为定义了一个模块
2:导入模块
模块要想使用,首先要导入模块,模块的导入有以下的几种方式:
- import module
- from module.x.x import x
- from module.x.x import x as rename
- from module.x.x import *
导入模块其实就是告诉python解释器去解释哪个py文件
- 导入一个py文件,解释器解释该py文件
- 导入一个包,解释器解释该包下的__init__.py文件
导入模块的路径
1: import sys
2: print sys.path
3: 结果:
4: [‘E:\\\\python\\\\day5‘, ‘E:\\\\python‘, ‘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‘]
还可以往里追加你想要的路径:sys.path.append(‘路径’)
通过os模块可以获取各种目录,例如:
1: import sys
2: import os
3: pre_path = os.path.abspath(‘../‘)
4: print pre_path
5: sys.path.append(pre_path)
开源模块
下载安装
方式一:
# yum # pip # apt-get |
方式二:
# 下载源码 # 解压源码 # 进入目录 # 编译解码 python setup.py build # 安装源码 python setup.py install |
注释:
因为是源码安装,需要使用gcc和python开发环境
yum –y install gcc yum –y install python-devel |
安装成功后,模块会自动安装到sys.path中的某个目录
导入模块
和自定义模块中的导入方法是一致的
范例:
模块paramiko
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作。fabric和ansible内部的远程管理就是使用paramiko来实现的
1:下载安装
# pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto # 下载安装 pycrypto wget http://files.cnblogs.com/files/wupeiqi/pycrypto-2.6.1.tar.gz tar -xvf pycrypto-2.6.1.tar.gz cd pycrypto-2.6.1 python setup.py build python setup.py install # 进入python环境,导入Crypto检查是否安装成功 # import Crypto # 下载安装 paramiko wget http://files.cnblogs.com/files/wupeiqi/paramiko-1.10.1.tar.gz tar -xvf paramiko-1.10.1.tar.gz cd paramiko-1.10.1 python setup.py build python setup.py install # 进入python环境,导入paramiko检查是否安装成功 # import paramiko
2:使用模块
执行命令--通过用户名和密码连接服务器
#!/usr/bin/env python # -*- coding:utf-8 -*- import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(‘10.0.0.9‘,22,‘root‘,‘123456‘) stdin,stdout,stderr = ssh.exec_command(‘df‘) print stdout.read() ssh.close() 结果: [email protected]:/server/scripts# python 10.py Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda3 19276064 1532552 16757656 9% / tmpfs 508148 0 508148 0% /dev/shm /dev/sda1 194241 36013 147988 20% /boot
内置模块
1:os
用于提供系统级别的操作
import os os.getcwd() # 获取当前工作目录 os.chdir() # 改变当前脚本工作目录;相当于shell下cd os.curdir # 返回当前目录:(‘..‘) os.pardir # 获取当前目录的父目录的字符串名:(‘..‘) os.makedirs(‘dirname1/dirname2‘)# 可生成多层递归目录 os.removedirs(‘dirname1‘) # 若目录为空,则删除;并递归到上一级目录;若也为空,则删除,依此类推 os.mkdir(‘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规范化的绝对路径 os.path.split() # 将path分割成目录和文件名二元组返回 os.path.dirname() # 返回path的目录,其实就是os.path.split(path)的第一个元素 os.path.basename() # 返回path最后的文件名。如果path是以/或\\结尾的的,返回是空值 os.path.exists() # 如果路径存在则返回True os.path.isabs() # 如果path是绝对路径,则返回True os.path.isfile() # 如果path是一个存在的文件,返回值为True os.path.isdir() # 如果path是一个存在的目录,返回值为True os.path.join() # 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 os.path.getatime(path) # 返回path所指向的文件或者目录的最后存取时间 os.path.getmtime(path) # 返回path所指向的文件或者目录的最后修改时间
2:sys
用于提供对解释器相关的操作
sys.argv # 命令行参数list,第一个元素是程序本身路径 sys.exit(n) # 退出程序,正常退出时exit(0) sys.version # 获取python解释程序的版本信息 sys.maxint # 最大的int值 sys.path # 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform # 返回操作系统平台名称 sys.stdout.write(‘please:‘) val = sys.stdin.readline()[:-1]
3:hashlib
用于加密想关的操作,代替了MD5模块和sha模块
import hashlib hash = hashlib.md5(‘123456‘) # 添加一个自定义的Key hash.update(‘admin‘) # 实际要加密的Key print hash.hexdigest() # 输出最终加密后的值 # 结果: b9d11b3be25f5a1a7dc8ca04cd310b28 #========================================================================================================使用hmac模块,他在内部对我们创建的key和内容再进行处理后再加密
import hmac h = hmac.new(‘123456‘) h.update(‘admin‘) print h.hexdigest() # 结果: 20238ad293024e2ea2f505db927cd52e
以上是关于Python-装饰器详解的主要内容,如果未能解决你的问题,请参考以下文章