1、装饰器原理

def f1(arg):
print '验证'
arg() def func():
print '' #、将被调用函数封装到另外一个函数
func = f1(func)
#、对原函数重新赋值
func()

现在有这样一种需求,原来的基础设施组提供的API接口函数需要都添加验证功能,解决的方法如下:

def auth(func):
def inner(): #添加验证功能
print 'before'
func()
return inner def f1(): #原来的函数
print 'f1' ret1 = auth(f1) = def inner(): #func()<====>f1()
print 'before'
func() #执行原来的f1函数 f1 = auth(f1) = def inner(): #将f1函数进行重命名,会添加验证功能
print 'before'
func()
f1() #执行新的f1函数

事实上Python提供的语法,可以将上述功能自动实现:

def auth(func):
def inner():
print 'before'
func()
return inner
@auth
def f3():
print 'f3' 此处的@auth有两层含义:
1、func() === f3()
2、将auth()函数的返回值作为f3()函数的返回值

2、函数含参数的装饰器

def auth_arg(func):   #含参数的装饰器必须传入参数
def inner(arg):
print 'before'
func(arg)
print 'after'
return inner @auth_arg
def f2(arg): #执行函数
print arg
basic.f2('1.1.1.1')    #调用函数

3、装饰器的内层函数设置为动态参数

def auth_arg(func):
def inner(*arg,**kwargs):
print 'before'
func(*arg,**kwargs)
print 'after'
return inner @auth_arg
def f1():
print 'f1'
@auth_arg
def f2(arg):
print arg 调用:任意调用
import basic

basic.f1()
print '======' basic.f2('1.1.1.1') 简单总结:
在写装饰器的时候,如果有参数传入,至少要写两层函数:
1、第一层(外层)函数传入函数func,返回第二层的函数名,不执行函数;
2、第二层传入参数,并return 第一层传入的函数的执行结果;

4、简单回顾

1、装饰器是一个函数,至少两层
2、执行auth函数,被装饰的函数作为参数auth(foo),auth函数的返回值赋值给被装饰的函数的函数名;
3、动态参数
4、函数的返回值
5、多装饰器
6、至少三层,三层如何使用?

5、装饰器的返回值

def auth(func):
def inner(*arg,**kwargs):
print 'before'
temp = func(*arg,**kwargs)
print 'after'
return temp
return inner @auth
def fetch_server_list(arg): #fetch_server_list === func
server_list = ['c1','c2','c3']
return server_list
import basic

ret_list = basic.fetch_server_list('test')      
print ret_list

6、利用装饰器实现登录验证

#Basic.py的内容
def login(): #登录验证函数
name = 'Charles'
if name == 'Charles':
return True
else:
return False def auth(func):
def inner(*arg,**kwargs):
is_login = login()
# if is_login:
# pass
# else:
# return "非法请求"
if not is_login:
return '非法请求'
temp = func(*arg,**kwargs)
print 'after'
return temp
return inner @auth
def fetch_server_list(arg):
server_list = ['c1','c2','c3']
return server_list #调用b1.py
import basic

ret_list = basic.fetch_server_list('test')
print ret_list

7、利用python装饰器实现token登录验证

#Basic.py
def login(key):
local = "dddddddddddddddddddddddd"
if local == key:
return True
else:
return False def auth(func):
def inner(*arg,**kwargs):
key = kwargs['token']
is_login = login(key)
# if is_login:
# pass
# else:
# return "非法请求"
if not is_login:
return '非法请求'
temp = func(*arg,**kwargs)
print 'after'
return temp
return inner @auth
def fetch_server_list(arg):
server_list = ['c1','c2','c3']
return server_list 调用:
import basic
key = "dddddddddddddddddddddddd"
ret_list = basic.fetch_server_list('test',token=key)
print ret_list 此时执行会报错

E:\python\python.exe E:/11S_05day/b1.py
Traceback (most recent call last):
File "E:/11S_05day/b1.py", line 12, in <module>
ret_list = basic.fetch_server_list('test',token=key)
File "E:\11S_05day\basic.py", line 99, in inner
temp = func(*arg,**kwargs)
TypeError: fetch_server_list() got an unexpected keyword argument 'token'

fetch_server_list函数只允许传入一个参数

解决方法:
def login(key):
local = "dddddddddddddddddddddddd"
if local == key:
return True
else:
return False def auth(func):
def inner(*arg,**kwargs):
#key = kwargs['token']
#del kwargs['token']
key = kwargs.pop('token') #加粗的上述语句等价,获取之后删除
is_login = login(key)
# if is_login:
# pass
# else:
# return "非法请求"
if not is_login:
return '非法请求'
temp = func(*arg,**kwargs)
print 'after'
return temp
return inner @auth
def fetch_server_list(arg):
server_list = ['c1','c2','c3']
return server_list

8、多装饰器

def w1(func):
def inner():
print "w1,before"
func()
print "w1,after"
return inner def w2(func):
def inner():
print "w2,before"
func()
print "w2,after"
return inner @w2
@w1
def foo():
print "foo"
foo() 1、登录验证
2、用户权限验证

9、装饰器之加参数(至少三层)

def Filter(before_func,after_func):
def outer(main_func):
def wrapper(request,kargs): before_result = before_func(request,kargs)
if(before_func !=None):
return before_func; 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(f1,f2) #等价于 outer函数 #1、先执行函数Filter(f1,f2),得到返回值outer
#2、将outer函数的返回值赋值给被装饰的函数的函数名
def Index(request,kargs):
print "index"

Index(11,22)
ret = Filter(f1,f2) =outer

解释器执行流程:

Filter(before_func,after_func)--->Filter(f1,f2)--->outer(main_func)--->outer--->@outer(Index==wrapper)--->wrapper(11,22)

装饰器参考:http://www.cnblogs.com/wupeiqi/articles/4980620.html#3546425

10、python递归原理

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

11、python递归的返回值

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
def func(arg1,arg2):
if arg1 == 0:
print arg1,arg2
arg3 = arg1 + arg2
if arg3 > 1000:
return arg3
func(arg2,arg3)
result = func(0,1)
print result #返回值为None,原因是函数的返回值return是将值返回给他的调用者,arg3的值返回给它的上一个func函数了,但是上一个函数没有return E:\python\python.exe E:/11S_05day/rescur.py
0 1
None

正确的代码为如下:

def func(arg1,arg2):
if arg1 == 0:
print arg1,arg2
arg3 = arg1 + arg2
if arg3 > 1000:
return arg3
return func(arg2,arg3) #返回结果,依次递归
result = func(0,1)
print result 结果为:
E:\python\python.exe E:/11S_05day/rescur.py
0 1
1597

12、python模块的导入

在window上使用第三方模块的时候,模块的安装目录为:E:\python\Lib\site-packages

import sys
print sys.path #python默认找模块的路径,是一个列表 E:\python\python.exe E:/11S_05day/model.py
['E:\\11S_05day', 'E:\\11S_05day', 'C:\\Windows\\SYSTEM32\\python27.zip', 'E:\\python\\DLLs', 'E:\\python\\lib', 'E:\\python\\lib\\plat-win', 'E:\\python\\lib\\lib-tk', 'E:\\python', 'E:\\python\\lib\\site-packages'] 因为python默认寻找模块的路径sys.path为一个列表,如果有需要导入的模块不在该列表当中,那么可以将该需要导入的模块的路径append到列表sys.path中
import sys
sys.path.append("E:\\")
print sys.path

python模块导入的三种方式:

import sys

from sys import argv

from mysys import argv as test

如果导入的是python的包,那么就存在init文件,在python包被导入的时候,先执行__init__文件内容,如果没有该文件,那么就无法找到其他.py文件.

如果单单是文件夹,那么不包含__init__文件。

12、os和sys模块

os:系统相关的模块

###os.walk方法,用于遍历指定目录下的文件和目录,该方法本生是一个生成器,如下:
os.walk('/scripts/shell')
<generator object walk at 0x8c69edc> 除了使用for循环遍历找出文件夹下的目录或者文件之外,还可以通过.next()方法找出文件夹下面的文件或者目录,如下:
>>> print os.walk('/scripts/shell').next()
('/scripts/shell', ['CTPHPRestart', 'ConnectivitiesTests'], ['ConnectivitiesTests.zip', 'CTPHPRestart.zip']) #生成元组,包含文件夹的名称,目录和文件,目录和文件分别用列表表示
>>> print os.walk('/scripts/shell').next()[]
/scripts/shell
>>> print os.walk('/scripts/shell').next()[] #目录
['CTPHPRestart', 'ConnectivitiesTests']
>>> print os.walk('/scripts/shell').next()[] #文件
['ConnectivitiesTests.zip', 'CTPHPRestart.zip']

sys:解释器相关的模块

subprocess是python管理子进程的模块,方法call执行成功返回0,方法check_call执行成功返回0,否则抛出异常;
Popen在创建子进程之后,主进程不会等待子进程执行完毕,除非调用wait方法
import subprocess
aa=subprocess.Popen('ls -l',shell=True)
aa.wait() #如果不调用wait方法,子进程会block,而print后面的内容会先打印出来;
print 'test is finished!!!'

Popen

child1=subprocess.Popen('cat /etc/passwd',shell=True,stdout=subprocess.PIPE)    #PIPE是缓存区,可以指定将输入、输出或者错误输出放入缓冲区中
#print child1.stdout.read()
with open('test.txt','wb') as f:
f.write(child1.stdout.read())

子程序的输入、输出和错误输出控制

13、python内置模块ConfigParser

配置文件i.cfg内容为:
[section1]
k1=123
k2=Charles [section2]
name = eric
age = 18 import ConfigParser config = ConfigParser.ConfigParser()
config.read('i.cfg') # ########## 读 ##########
secs = config.sections()
print secs 结果为:
E:\python\python.exe E:/11S_05day/index.py
['section1', 'section2'] #######################
options = config.options('section1')
print options 结果为:
E:\python\python.exe E:/11S_05day/index.py
['k1', 'k2'] #######################
item_list = config.items('section1')
print item_list 结果为:
E:\python\python.exe E:/11S_05day/index.py
[('k1', ''), ('k2', 'Charles')] #######################
val = config.get('section1','k1')
print val 结果为:
E:\python\python.exe E:/11S_05day/index.py
123 val = config.getint('section1','k1') #等价于上述语句,再加int(val)
print val # ########## 改写 ##########
sec = config.remove_section('section1') #只在内存中删除
config.write(open('i.cfg', "w")) #将删除的结果写入文件 结果: [section1]被删除
[section2]
name = eric
age = 18 ########################
sec = config.has_section('section1') #是否存在section1
print sec ########################
config.set('section1','k1',11111) #添加option
config.write(open('i.cfg', "w")) ########################
config.remove_option('section1','k1') #删除option
config.write(open('i.cfg', "w"))

配置文件应于示例:在不使用数据库的情况下,可以将数据列表写入配置文件中,在每次操作的时候,将主机列表添加到列表中,循环列表,结合paramiko模块,远程执行SHELL命令,返回结果;

14、python内置模块hashlib

################################MD5加密
import md5
hash = md5.new()
hash.update('admin')
ret = hash.hexdigest()
print ret 结果为:
E:\python\python.exe E:/11S_05day/index.py
21232f297a57a5a743894a0e4a801fc3

事实上加密算法有很多,在python中很多加密算法散落在不同的模块中,而hashlib将众多的加密算法集中到该模块中

import hashlib
hash = hashlib.md5('') #‘123’为加密的key
hash.update('admin')
print hash.hexdigest()

python 装饰器、递归原理、模块导入方式的更多相关文章

  1. 【低门槛 手把手】python 装饰器(Decorators)原理说明

    本文目的是由浅入深地介绍python装饰器原理 装饰器(Decorators)是 Python 的一个重要部分 其功能是,在不修改原函数(类)定义代码的情况下,增加新的功能 为了理解和实现装饰器,我们 ...

  2. python装饰器+递归+冒泡排序

    冒泡排序 li = [33, 2, 10, 1,23,23523,5123,4123,1,2,0] for k in range(1,len(li)): for i in range(len(li) ...

  3. python装饰器的原理

    装饰器的原理就是利用<闭包函数>来实现,闭包函数的原理就是包含内层函数的return和外层环境变量:

  4. python 装饰器和 functools 模块

    转自:http://blog.jkey.lu/2013/03/15/python-decorator-and-functools-module/ 什么是装饰器? 在 python 语言里第一次看到装饰 ...

  5. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  6. 粗浅聊聊Python装饰器

    浅析装饰器 通常情况下,给一个对象添加新功能有三种方式: 直接给对象所属的类添加方法: 使用组合:(在新类中创建原有类的对象,重复利用已有类的功能) 使用继承:(可以使用现有类的,无需重复编写原有类进 ...

  7. Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发

    本节大纲 迭代器&生成器 装饰器  基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...

  8. 【转】【python】装饰器的原理

    写在前面: 在开发OpenStack过程中,经常可以看到代码中的各种注解,自己也去查阅了资料,了解了这是python中的装饰器,因为弱类型的语言可以将函数当成返回值返回,这就是装饰器的原理. 虽然说知 ...

  9. 对于python装饰器结合递归的进一步理解

    对于python装饰器结合递归的进一步理解 代码如下: import functools def memoize(fn): print('start memoize') known = dict() ...

随机推荐

  1. ipv6 操作

    netsh interface teredo set state disablednetsh interface ipv6 add v6v4tunnel interface=IP6Tunnel 120 ...

  2. 第9章 应用层(1)_域名系统DNS

    1. 域名系统DNS 1.1 主机名和域名的关系 (1)完全限定域名(Fully Qualified Domain Name, FQDN) = 主机名 + 域名 ①一个域名下可以有多个服务器/主机(如 ...

  3. jQuery实现评论弹幕、弹幕漂浮、滚动代码

    1.html代码和jquery代码: <!DOCTYPE html> <html> <head lang="en"> <meta char ...

  4. RabbitMQ install (Ubuntu)

    1. key 1) Online way apt-key adv --keyserver "hkps.pool.sks-keyservers.net" --recv-keys &q ...

  5. IIS7.5和IIS8如何设置FTP的pasv端口范围

    如果不设置端口范围,在防火墙开启的情况下,连接FTP时可能出现列表错误的现象,下面介绍下如何设置FTP的pasv端口范围.. 一.首先打开IIS选择服务器会进入全局设置,再双击FTP防火墙支持 二.设 ...

  6. HTTP请求返回值所代表的含义

    一些常见的状态码为: 200 - 服务器成功返回网页(表示请求成功) 404 - 请求的网页不存在(可能是网络的问题,也可能是网页没办法访问不代表网页不存在) 503 - 服务器超时(服务器故障) 下 ...

  7. Struts2学习:interceptor(拦截器)的使用

    对于需要登陆验证.权限验证等功能的网站,每一次请求,每一个action都写一段验证的代码,未免显得冗余且不易维护.struts2提供了拦截器interceptor,为这些页面提供一个切面,或者说公共组 ...

  8. 数组转换成json key-value形式

    eg1(数组中包含的是数组): var jsonData = {}; var arr = [[1, 'boy', 'dabing'], [2, 'girl', 'dabing']]; for (var ...

  9. 微信小程序:block的隐藏

    <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性. 所以 hidden.display等通用隐藏元素的方法对block是无效的 想要隐藏blo ...

  10. 运行vbs脚本

    VBS是基于Visual Basic的脚本语言. VBS的全称是:Microsoft Visual Basic Script Edition.(微软公司可视化BASIC脚本版). 其语言类似Visua ...