1、装饰器原理

  1. def f1(arg):
  2. print '验证'
  3. arg()
  4.  
  5. def func():
  6. print ''
  7.  
  8. #、将被调用函数封装到另外一个函数
  9. func = f1(func)
  10. #、对原函数重新赋值
  11. func()

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

  1. def auth(func):
  2. def inner(): #添加验证功能
  3. print 'before'
  4. func()
  5. return inner
  6.  
  7. def f1(): #原来的函数
  8. print 'f1'
  9.  
  10. ret1 = auth(f1) = def inner(): #func()<====>f1()
  11. print 'before'
  12. func() #执行原来的f1函数
  13.  
  14. f1 = auth(f1) = def inner(): #将f1函数进行重命名,会添加验证功能
  15. print 'before'
  16. func()
  17. f1() #执行新的f1函数

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

  1. def auth(func):
  2. def inner():
  3. print 'before'
  4. func()
  5. return inner
  6. @auth
  7. def f3():
  8. print 'f3'
  9.  
  10. 此处的@auth有两层含义:
    1func() === f3()
    2、将auth()函数的返回值作为f3()函数的返回值

2、函数含参数的装饰器

  1. def auth_arg(func): #含参数的装饰器必须传入参数
  2. def inner(arg):
  3. print 'before'
  4. func(arg)
  5. print 'after'
  6. return inner
  7.  
  8. @auth_arg
  9. def f2(arg): #执行函数
  10. print arg
  1. basic.f2('1.1.1.1') #调用函数
  1.  

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

  1. def auth_arg(func):
  2. def inner(*arg,**kwargs):
  3. print 'before'
  4. func(*arg,**kwargs)
  5. print 'after'
  6. return inner
  7.  
  8. @auth_arg
  9. def f1():
  10. print 'f1'
  11. @auth_arg
  12. def f2(arg):
  13. print arg
  14.  
  15. 调用:任意调用
  1. import basic
  2.  
  3. basic.f1()
    print '======'
  4.  
  5. basic.f2('1.1.1.1')
  6.  
  7. 简单总结:
    在写装饰器的时候,如果有参数传入,至少要写两层函数:
    1、第一层(外层)函数传入函数func,返回第二层的函数名,不执行函数;
    2、第二层传入参数,并return 第一层传入的函数的执行结果;

4、简单回顾

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

5、装饰器的返回值

  1. def auth(func):
  2. def inner(*arg,**kwargs):
  3. print 'before'
  4. temp = func(*arg,**kwargs)
  5. print 'after'
  6. return temp
  7. return inner
  8.  
  9. @auth
  10. def fetch_server_list(arg): #fetch_server_list === func
  11. server_list = ['c1','c2','c3']
  12. return server_list
  1. import basic
  2.  
  3. ret_list = basic.fetch_server_list('test')
    print ret_list

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

  1. #Basic.py的内容
    def login(): #登录验证函数
  2. name = 'Charles'
  3. if name == 'Charles':
  4. return True
  5. else:
  6. return False
  7.  
  8. def auth(func):
  9. def inner(*arg,**kwargs):
  10. is_login = login()
  11. # if is_login:
  12. # pass
  13. # else:
  14. # return "非法请求"
  15. if not is_login:
  16. return '非法请求'
  17. temp = func(*arg,**kwargs)
  18. print 'after'
  19. return temp
  20. return inner
  21.  
  22. @auth
  23. def fetch_server_list(arg):
  24. server_list = ['c1','c2','c3']
  25. return server_list
  26.  
  27. #调用b1.py
  1. import basic
  2.  
  3. ret_list = basic.fetch_server_list('test')
    print ret_list

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

  1. #Basic.py
    def login(key):
  2. local = "dddddddddddddddddddddddd"
  3. if local == key:
  4. return True
  5. else:
  6. return False
  7.  
  8. def auth(func):
  9. def inner(*arg,**kwargs):
  10. key = kwargs['token']
  11. is_login = login(key)
  12. # if is_login:
  13. # pass
  14. # else:
  15. # return "非法请求"
  16. if not is_login:
  17. return '非法请求'
  18. temp = func(*arg,**kwargs)
  19. print 'after'
  20. return temp
  21. return inner
  22.  
  23. @auth
  24. def fetch_server_list(arg):
  25. server_list = ['c1','c2','c3']
  26. return server_list
  27.  
  28. 调用:
  1. import basic
    key = "dddddddddddddddddddddddd"
    ret_list = basic.fetch_server_list('test',token=key)
    print ret_list
  2.  
  3. 此时执行会报错

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'

  1. fetch_server_list函数只允许传入一个参数
  2.  
  3. 解决方法:
  1. def login(key):
    local = "dddddddddddddddddddddddd"
    if local == key:
    return True
    else:
    return False
  2.  
  3. 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
  4.  
  5. @auth
    def fetch_server_list(arg):
    server_list = ['c1','c2','c3']
    return server_list

8、多装饰器

  1. def w1(func):
  2. def inner():
  3. print "w1,before"
  4. func()
  5. print "w1,after"
  6. return inner
  7.  
  8. def w2(func):
  9. def inner():
  10. print "w2,before"
  11. func()
  12. print "w2,after"
  13. return inner
  14.  
  15. @w2
  16. @w1
  17. def foo():
  18. print "foo"
  19. foo()
  20.  
  21. 1、登录验证
    2、用户权限验证

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

  1. def Filter(before_func,after_func):
  2. def outer(main_func):
  3. def wrapper(request,kargs):
  4.  
  5. before_result = before_func(request,kargs)
  6. if(before_func !=None):
  7. return before_func;
  8.  
  9. main_result = main_func(request,kargs)
  10. if(main_result !=None):
  11. return main_result;
  12.  
  13. after_result = after_func(request,kargs)
  14. if(after_result !=None):
  15. return after_result;
  16. return wrapper
  17. return outer
  18.  
  19. @Filter(f1,f2) #等价于 outer函数 #1、先执行函数Filter(f1,f2),得到返回值outer
    #2、将outer函数的返回值赋值给被装饰的函数的函数名
  20. def Index(request,kargs):
  21. print "index"

  22. Index(11,22)
  23. 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递归原理

  1. def func(arg1,arg2):
  2. if arg1 == 0:
  3. print arg1,arg2
  4. arg3 = arg1 + arg2
  5. print arg3
  6. func(arg2,arg3)
  7. func(0,1)

11、python递归的返回值

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

正确的代码为如下:

  1. def func(arg1,arg2):
  2. if arg1 == 0:
  3. print arg1,arg2
  4. arg3 = arg1 + arg2
  5. if arg3 > 1000:
  6. return arg3
  7. return func(arg2,arg3) #返回结果,依次递归
  8. result = func(0,1)
  9. print result
  10.  
  11. 结果为:
  12. E:\python\python.exe E:/11S_05day/rescur.py
  13. 0 1
  14. 1597

12、python模块的导入

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

  1. import sys
  2. print sys.path #python默认找模块的路径,是一个列表
  3.  
  4. E:\python\python.exe E:/11S_05day/model.py
  5. ['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']
  6.  
  7. 因为python默认寻找模块的路径sys.path为一个列表,如果有需要导入的模块不在该列表当中,那么可以将该需要导入的模块的路径append到列表sys.path
  1. 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:系统相关的模块

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

sys:解释器相关的模块

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

Popen

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

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

13、python内置模块ConfigParser

  1. 配置文件i.cfg内容为:
  2. [section1]
  3. k1=123
  4. k2=Charles
  5.  
  6. [section2]
  7. name = eric
  8. age = 18
  9.  
  10. import ConfigParser
  11.  
  12. config = ConfigParser.ConfigParser()
  13. config.read('i.cfg')
  14.  
  15. # ########## 读 ##########
  16. secs = config.sections()
  17. print secs
  18.  
  19. 结果为:
  20. E:\python\python.exe E:/11S_05day/index.py
  21. ['section1', 'section2']
  22.  
  23. #######################
  24. options = config.options('section1')
  25. print options
  26.  
  27. 结果为:
  28. E:\python\python.exe E:/11S_05day/index.py
  29. ['k1', 'k2']
  30.  
  31. #######################
  32. item_list = config.items('section1')
  33. print item_list
  34.  
  35. 结果为:
  36. E:\python\python.exe E:/11S_05day/index.py
  37. [('k1', ''), ('k2', 'Charles')]
  38.  
  39. #######################
  40. val = config.get('section1','k1')
  41. print val
  42.  
  43. 结果为:
  44. E:\python\python.exe E:/11S_05day/index.py
  45. 123
  46.  
  47. val = config.getint('section1','k1') #等价于上述语句,再加int(val)
  48. print val
  49.  
  50. # ########## 改写 ##########
  51. sec = config.remove_section('section1') #只在内存中删除
  52. config.write(open('i.cfg', "w")) #将删除的结果写入文件
  53.  
  54. 结果: [section1]被删除
  55. [section2]
  56. name = eric
  57. age = 18
  58.  
  59. ########################
  60. sec = config.has_section('section1') #是否存在section1
  61. print sec
  62.  
  63. ########################
  64. config.set('section1','k1',11111) #添加option
  65. config.write(open('i.cfg', "w"))
  66.  
  67. ########################
  68. config.remove_option('section1','k1') #删除option
  69. config.write(open('i.cfg', "w"))

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

14、python内置模块hashlib

  1. ################################MD5加密
    import md5
  2. hash = md5.new()
  3. hash.update('admin')
  4. ret = hash.hexdigest()
  5. print ret
  6.  
  7. 结果为:
  8. E:\python\python.exe E:/11S_05day/index.py
  9. 21232f297a57a5a743894a0e4a801fc3

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

  1. import hashlib
  2. hash = hashlib.md5('') #‘123’为加密的key
  3. hash.update('admin')
  4. 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. Delphi2010/XE2下隐藏程序系统任务栏的图标

    Delphi7代码: SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW); 以上的代码在Delphi7中可以用,但是在Delp ...

  2. hadoop 分布式机群搭建

    描述:鉴于本地电脑内存限制,采用三台虚机安装此环境. 主机名,分别为master.slave1.slave2. zookeeper分别安装这三台机器上,master和slave1做主从备份, slav ...

  3. Java笔试面试题整理第一波

    转载至:http://blog.csdn.net/shakespeare001/article/details/51151650 作者:山代王(开心阳) 本系列整理Java相关的笔试面试知识点,其他几 ...

  4. 06 I/O重定向与管道符

    首先,我们知道我们的计算机结构,在第一节的时候已经介绍过了,CPU进行数据运算,同时控制器负责指令的发送,而内存则是数据存储的地方,CPU读取的数据均从内存中调取.电脑除了CPU和内存外,我们还有I/ ...

  5. Java 6- Java 运算符

    计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量.我们可以把运算符分成以下几组: 算术运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 其他运 ...

  6. TableStore:单行操作

    说明: 首先需要添加TableStore的依赖 <dependency> <groupId>com.aliyun.openservices</groupId> &l ...

  7. ASCII、Unicode和UTF-8

    转自廖雪峰的官方网站:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138 ...

  8. BZOJ2054 疯狂的馒头 并查集

    题意:懒得写了有空再补上 链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2054 离线从后往前做,并查集维护下一个没染色的就可以啦- #incl ...

  9. web中的集群与分布式

    面试中经常会提到 集群 和 分布式.下面就来分别说说这两个在web开发中经常用到的开发方式. 集群: 集群是一组协同工作的服务实体,用以提供比单一服务实体更具扩展性与可用性的服务平台.在客户端看来,一 ...

  10. hdfs dfsadmin 命令详解

    hdfs dfsadmin [-report [-live] [-dead] [-decommissioning]] [-safemode <enter | leave | get | wait ...