zoukankan      html  css  js  c++  java
  • python之旅5【第五篇】

    装饰器详解

    函数刚开始不解析内部,只是放进内存

    装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作

     1 下面以一个函数开始,理解下面概念

    1 def  foo():
    2     print 'foo'
    3 
    4 foo 是函数
    5 foo()  是执行函数

    2 看下面的一个函数执行过程

    1 def  f1(arg):
    2     arg()
    3 
    4 def func():
    5     print '123'
    6 
    7 f1(func)

    3 上面的理解之后,看下面一个函数执行过程

    1 def auth(func):
    2     def wrapper():
    3         print "before"
    4         func()
    5     return wrapper
    6 def f1():
    7     print "f1"
    8 auth(f1)

     4 接着上边的,如何执行内部的内容, 引入装饰器

    还是上面的函数,换了执行方式

    1 def auth(func):
    2     def wrapper():
    3         print "before"
    4         func()
    5     return wrapper
    6 def f1():
    7     print "f1"
    8 ret=auth(f1)
    9 ret()

     5 装饰器引入

     1 def auth(func):
     2 def wrapper():
     3     print "before"
     4     func()
     5 return wrapper
     6 
     7 @auth
     8 def f1():
     9 print "f1
    10 
    11 @auth=>auth(f1)==>f1=auth(f1)=def wrapper():
    12                                print "before"
    13                                func()
    14 接下来再执行f1()就相当于执行了wrapper()函数
    主要过程是执行auth函数,被装饰的函数作为参数传入auth--auth(f1),auth函数的返回值,赋值给被装饰的函数的函数名,---f1=wrapper

    6 装饰器含参数(一个参数)

     1 def auth(func):
     2     def inner(arg):
     3         print "before"
     4         func(arg)
     5     return inner
     6 @auth
     7 def f2(arg):
     8     print "f2" ,arg
     9 f2('test')
    10 
    11 结果
    12 before
    13 f2 test

    7 多个参数,动态参数

     1 def auth(func):
     2     def inner(*args,**kwargs):
     3         print "before"
     4         func(*arg,**kwargs)
     5         print 'after'
     6     return inner    
     7 
     8 @auth
     9 def f2(*args,**kwargs):
    10     print "f2"    
    11 
    12 f2('1.1.1.1') 

     8 含有返回值的装饰器

     1 def auth1(func):
     2     def inner(*arg,**kwargs):
     3         print 'before'
     4         temp = func(*arg,**kwargs)
     5         print 'after'
     6         return temp   #inner函数有了返回值
     7     return inner
     8 
     9 @auth1
    10 def fetch_list(arg):
    11     print "fetch_list"
    12     server_list = [11,22,33]
    13     return server_list
    14 
    15 ret = fetch_list('test')
    16 print ret 
    17 
    18 结果
    19 before
    20 fetch_list
    21 after
    22 [11, 22, 33]

    9 装饰器实现登录验证

    主要就是增加了一个login函数

     1 def login():
     2     name = 'dicky'
     3     if name == 'dicky1':
     4         return True
     5     else:
     6         return False
     7 
     8 def auth3(func):
     9     def inner(*args,**kwargs):
    10         is_login = login()
    11         if not is_login:
    12             return "invild"
    13         temp = func(*args,**kwargs)
    14         return temp
    15     return inner
    16 @auth3
    17 def fetch_list(arg):
    18     print "fetch_list"
    19     server_list = [11,22,33]
    20     return server_list
    21 ret=fetch_list('test')
    22 print ret
    23 
    24 结果
    25 invild

    10 装饰器实现token验证,跟上面的login差不多

     1 def login1(key):
     2     name = 'alex1'
     3     local = 'afcadfsgdgwegsfbdfgsgsfwe'
     4     if local == key:
     5         return True
     6     else:
     7         return False
     8 def auth3(func):
     9     def inner(*arg,**kwargs):
    10         # key=kwargs['token']
    11         # del kwargs['token']
    12         key = kwargs.pop('token')  #删除多传入的参数
    13         is_login = login1(key)
    14         if not is_login:
    15             return "invild"
    16         print 'before'
    17         temp = func(*arg,**kwargs)  #上面删除了多传入的参数,这里就不会报错了
    18         print 'after'
    19         return temp
    20     return inner
    21 
    22 @auth3
    23 def fetch_list(arg):
    24     print "fetch_list"
    25     server_list = [11,22,33]
    26     return server_list
    27 
    28 key = 'afcadfsgdgwegsfbdfgsgsfwe'
    29 ret = fetch_list('test',token=key)
    30 print "llllllllll"
    31 print ret

     11 多装饰器

    先执行外部装饰器,然后在执行内部装饰器

     1 def w1(func):
     2     def inner():
     3         print 'w1 before'
     4         func()
     5         print 'w1 after'
     6     return inner
     7 def w2(func):
     8     def inner():
     9         print 'w2 after'
    10         func()
    11         print 'w2 after'
    12     return inner
    13 @w2
    14 @w1
    15 def foo():
    16     print 'foo'
    17 
    18 foo()
    19 结果
    20 w2 after
    21 w1 before
    22 foo
    23 w1 after
    24 w2 after

    12 装饰器附加参数

     1 def Before(request,kargs):
     2     print 'before'
     3       
     4 def After(request,kargs):
     5     print 'after'
     6   
     7   
     8 def Filter(before_func,after_func):
     9     def outer(main_func):
    10         def wrapper(request,kargs):
    11               
    12             before_result = before_func(request,kargs)
    13             if(before_result != None):
    14                 return before_result;
    15               
    16             main_result = main_func(request,kargs)
    17             if(main_result != None):
    18                 return main_result;
    19               
    20             after_result = after_func(request,kargs)
    21             if(after_result != None):
    22                 return after_result;
    23               
    24         return wrapper
    25     return outer
    26       
    27 @Filter(Before, After)
    28 def Index(request,kargs):
    29     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): 2 @functools.wraps(func) 3 def inner(*args, **kwargs): 4 print(inner.__doc__) # None 5 return func() 6 return inner 7 8 @outer 9 def function(): 10 """ 11 asdfasd 12 :return: 13 """ 14 print('func') 15 16 function() 17 结果 18 asdfasd 19 :return: 20 21 func 22 23 #输出了原函数的__doc__内容

     二 递归

    1 编写数列

    1 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233377610987159725844181676510946177112865746368
    View Code

    函数如下

    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 
    8 
    9 func(0,1)
    View Code

     2 递归的返回值

    先看下面的一个简单例子

     1 def n5():
     2     return '1234'
     3 def n4():
     4     n5()
     5 def n3():
     6     n4()
     7 def n2():
     8     n3()
     9 def n1():
    10     n2()
    11 ret=n1()
    12 print ret
    13 
    14 结果None

    分析如下

    上面的函数首先执行
    n1()---n2()--n3()---n4()--n5()
    到执行到n5的时候有返回值,n5函数的返回值返回给调用n5函数的函数n4
    即res=n5()----def n4(): 但是n4没有返回值,n3也没有返回值,n2也没有返回值,n1也没有返回值,所以最后返回none
    改进一下,让他有返回值

     1 def n5():
     2     return '1234'
     3 def n4():
     4     return n5()
     5 def n3():
     6     return n4()
     7 def n2():
     8     return n3()
     9 def n1():
    10     return n2()
    11 ret=n1()
    12 print ret
    13 
    14 
    15 结果
    16 1234
    17 这样让它每次都有返回值
    View Code

     3 看下面的递归例子(改进了一下上边的数列例子)

     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     func(arg2,arg3)
     8 
     9 ret = func(0,1)
    10 print ret
    11 
    12 结果为None

    分析如下

    执行第一次func(0,1)没有返回值
    执行第二次func(1,1)也没有返回值
    ..........
    当执行到func(610,987)的时候,接着执行上面,arg=1597,满足条件,return返回1597,谁调用的返回给谁,也就是返回给func(610,987),但是在这之前执行func()函数却没有返回值,跟上面的例子差不多,所以最后返回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 
     9 ret = func(0,1)
    10 print ret
    11 
    12 结果
    13 1597
    View Code

     三模块

     模块分为三种:

    • 自定义模块
    • 内置模块
    • 开源模块

    自定义模块

    1

    2

    导入模块

    1 import module
    2 from module.xx.xx import xx
    3 from module.xx.xx import xx as rename  
    4 from module.xx.xx import *

    导入模块其实就是告诉Python解释器去解释那个py文件

    • 导入一个py文件,解释器解释该py文件
    • 导入一个包,解释器解释该包下的 __init__.py 文件
    1 模块路径
    2 import sys
    3 print sys.path
    4 结果
    5 ['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模块

     1 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
     2 os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
     3 os.curdir  返回当前目录: ('.')
     4 os.pardir  获取当前目录的父目录字符串名:('..')
     5 os.makedirs('dirname1/dirname2')    可生成多层递归目录
     6 os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
     7 os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
     8 os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
     9 os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
    10 os.remove()  删除一个文件
    11 os.rename("oldname","newname")  重命名文件/目录
    12 os.stat('path/filename')  获取文件/目录信息
    13 os.sep    输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"
    14 os.linesep    输出当前平台使用的行终止符,win下为"	
    ",Linux下为"
    "
    15 os.pathsep    输出用于分割文件路径的字符串
    16 os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
    17 os.system("bash command")  运行shell命令,直接显示
    18 os.environ  获取系统环境变量
    19 os.path.abspath(path)  返回path规范化的绝对路径
    20 os.path.split(path)  将path分割成目录和文件名二元组返回
    21 os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
    22 os.path.basename(path)  返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素
    23 os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
    24 os.path.isabs(path)  如果path是绝对路径,返回True
    25 os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
    26 os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
    27 os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
    28 os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
    29 os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
    View Code

    sys模块

    1 sys.argv           命令行参数List,第一个元素是程序本身路径
    2 sys.exit(n)        退出程序,正常退出时exit(0)
    3 sys.version        获取Python解释程序的版本信息
    4 sys.maxint         最大的Int值
    5 sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
    6 sys.platform       返回操作系统平台名称
    View Code
  • 相关阅读:
    Warning:detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd".
    Ubuntu16.04安装K8s步骤和踩坑记录【不错】
    修改主机名(/etc/hostname和/etc/hosts区别)
    Windows10内置Linux子系统初体验
    Docker Swarm常用命令
    Docker Swarm集群部署
    Docker容器CPU、memory资源限制
    Docker监控容器资源的占用情况
    修改Docker容器启动配置参数
    sort-colors——排序3种数字
  • 原文地址:https://www.cnblogs.com/Dicky-Zhang/p/7400278.html
Copyright © 2011-2022 走看看