• 装饰器详解


    装饰器?What?

    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:导入模块

    模块要想使用,首先要导入模块,模块的导入有以下的几种方式:

    1. import module
    2. from module.x.x import x
    3. from module.x.x import x as rename
    4. 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()
    结果:
    root@python:/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:	
      linux:
    
    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
    作者:曹小贱
             
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Spark源码走读6——Shuffle
    Spark源码走读5——Storage
    使用Gradle构建Android应用的渠道包
    轻松搞定面试中的二叉树题目
    QT中使用微软Speech API实现语音识别
    QT 相关资源(书籍、论坛、博客等。。。)整理...
    使用Cscope阅读大型工程Linux内核的源代码教程
    搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门
    RSA算法原理(二)
    RSA算法原理(一)
  • 原文地址:https://www.cnblogs.com/caoxiaojian/p/4990008.html
Copyright © 2020-2023  润新知