zoukankan      html  css  js  c++  java
  • python 装饰器、递归原理、模块导入方式

    1、装饰器原理

    def f1(arg):
        print '验证'
        arg()
    
    def func():
        print '12'
    
    #1、将被调用函数封装到另外一个函数
    func = f1(func)
    #2、对原函数重新赋值
    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:pythonpython.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_05dayasic.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:pythonpython.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:pythonpython.exe E:/11S_05day/rescur.py
    0 1
    1597

     12、python模块的导入

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

    import sys
    print sys.path     #python默认找模块的路径,是一个列表
    
    E:pythonpython.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()[0]
    /scripts/shell
    >>> print os.walk('/scripts/shell').next()[1]    #目录
    ['CTPHPRestart', 'ConnectivitiesTests']
    >>> print os.walk('/scripts/shell').next()[2]    #文件
    ['ConnectivitiesTests.zip', 'CTPHPRestart.zip']
    View Code

    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:pythonpython.exe E:/11S_05day/index.py
    ['section1', 'section2']
    
    
    #######################
    options = config.options('section1')
    print options
    
    结果为:
    E:pythonpython.exe E:/11S_05day/index.py
    ['k1', 'k2']
    
    #######################
    item_list = config.items('section1')
    print item_list
    
    结果为:
    E:pythonpython.exe E:/11S_05day/index.py
    [('k1', '123'), ('k2', 'Charles')]
    
    #######################
    val = config.get('section1','k1')
    print val
    
    结果为:
    E:pythonpython.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:pythonpython.exe E:/11S_05day/index.py 21232f297a57a5a743894a0e4a801fc3

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

    import hashlib
    hash = hashlib.md5('123')    #‘123’为加密的key
    hash.update('admin')
    print hash.hexdigest()
  • 相关阅读:
    Promise 解决回调地狱问题
    同步 异步 API 区别
    静态资源 读取方法
    路由
    HTTP 协议 get post 请求方式
    linux 查看日志
    putty完全使用手册--多窗口---git提交---连接数据库--自动日志显示
    strpos 返回0时 ,比较false 不能加单引号
    禁止使用test类的就是禁止使用本来的$this对象.可以调用父类的对象
    大D实例化model-->调用自定义类方法,大M调用原声model方法
  • 原文地址:https://www.cnblogs.com/cqq-20151202/p/5083696.html
Copyright © 2011-2022 走看看