一、nonlocal关键字

def outer():
    num = 0
    def inner():
        # 如果想在被嵌套的函数中修改外部函数变量(名字)的值
        nonlocal num  # 将 L 与 E(E中的名字需要提前定义) 的名字统一
        num = 10
        print(num) # 10
    inner()
    print(num)  # 10
outer()
print(num)  # name 'num' is not defined

二、装饰器

定义:

本质是函数,(装饰其他函数)就是为其他的函数添加功能。

开放封闭原则:

1、不能修改被装饰的函数的源代码

2、不能修改被装饰的函数的调用方式

理解装饰器的知识储备:

1、函数即‘变量’

2、高阶函数

3、嵌套函数

高阶函数+嵌套函数==装饰器

高阶函数:变量可以指向函数,函数的参数可以接收变量,那么一个函数就可以接收另一个函数作为参数,这就是高阶函数。

# 1、把一个函数名当作实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)

# 2、返回值中包含函数名(不修改函数的调用方式)

高阶函数实例:

def add(x,y,f):
    return f(x)+f(y)
res = add(3,-6,abs)
print(res)

装饰器写法:

def wrap(fn):
    def inner(*args,**kwargs):
        print("前增功能")
        result = fn(*args,**kwargs)
        print("后增功能")
        return result
    return inner

@wrap
def fn1():
    print("fn1的原有功能")
@wrap
def fn2(a,b):
    print("fn2的原有功能")
@wrap
def fn3():
    print("fn3的原有功能")
    return True
@wrap
def fn4(a,*,x):
    print("fn4的原有功能")
    return True

fn1()
fn2(10,20)
fn3()
fn4(10,x=20)

装饰器演示:

import time
def timmer(func):
    def warpper(*args,**kwargs):
        start_time=time.time()
        func()
        stop_time=time.time()
        print('the func run time is %s'%(stop_time-start_time))
    return warpper()

@timmer   #语法糖
def test1():
    time.sleep(3)
    print('in the test1')
test1()

有参有返的函数装饰器示例:

# 增加一个账号处理功能:3位及以上英文字母或汉字
def check_usr(fn):
    def inner(usr,pwd):
        if not (len(usr) >= 3 and usr.isalpha()):
            print("账号验证失败")
            return False
        result = fn(usr,pwd)  # login
        return result
    return inner

# 增加一个密码处理功能:6位及以上英文和数字
def check_pwd(fn):
    def inner(usr,pwd):
        if not (len(pwd) >= 6 and pwd.isalnum()):
            print("密码验证失败")
            return False
        return fn(usr,pwd)
    return inner

# 登录功能
@check_usr
@check_pwd
def login(usr,pwd):
    if usr == 'abc' and pwd == '123qwe':
        print("登陆成功")
        return True
    print("登录失败")
    return False

res = login('abc','123qwe')  # inner
print(res)

#总结
1、login有参数,所以inner与fn都有相同参数
2、login有返回值,所以inner与fn都有返回值

装饰器结合可变长参数

def wrap(fn):
    def inner(*args,**kwargs):
        result = fn(*args,**kwargs)
        print("新增功能")
        return result
    return inner

@wrap
def func(a,b,c,*,x,y,z):
    print(a,b,c,x,y,z)
    print("原有功能")

func(1,2,3,x=10,y=20,z=30)

带参装饰器

def outer(input_color):
    def wrap(fn):
        if input_color == 'red':
            info = '\033[31mnew action\033[0m'
        else:
            info = '\033[32mGreen:new action\033[0m'
        def inner(*args,**kwargs):
            result = fn(*args,**kwargs)
            print(info)
            return result
        return inner
    return wrap   # outer(color) --> wrap

color = input("color:")
@outer(color)
def func():
    print('func run')

func()

登录认证案例:

​
is_login = False  # 登陆状态

def login():
    global ​is_login
    usr = input("usr:")
    if not (len(usr) >= 3 and usr.isalpha()):
        print('账号验证失败')
        return False
    pwd = input("pwd:")
    if usr == 'abc' and pwd == '123qwe':
        print('login success')
        is_login = True
    else:
        print('login fail')
        is_login = False

# 完成一个登录状态校验的装饰器
def check_login(fn):
    def inner(*args,**kwargs):
        if is_login != True:
            print("你未登录")
            login()
        result = fn(*args,**kwargs)
        return result
    return inner

#查看个人主页
@check_login
def home():
    print("个人主页")

#销售功能
@check_login
def sale():
    print("可以销售")

home()
sale()

​

装饰器案例高级:

import time
user,passwd = 'shj','abc123'
def auth(auth_type):
    print("auth func:",auth_type)
    def outer_wrapper(func):
        def wrapper(*args,**kwargs):
            print("wrapper func args:",*args,**kwargs)
            if auth_type == 'local':
                username = input("Username:").strip()
                password = input("Password:").strip()
                if user==username and passwd==password:
                    print("User has passed authentication")
                    res = func(*args,**kwargs)
                    print("-------after authentication")
                    return res
                else:
                    exit("Invalid username or password")
            elif auth_type == 'ldap':
                print("It is so difficult !")
        return wrapper
    return outer_wrapper
def index():
    print("welcome to index page")
@auth(auth_type="local")  #相当于 home = wrapper()
def home():
    print("welcome to home page")
@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")

index()
home()
bbs()

python基础——8(装饰器)的更多相关文章

  1. python基础—函数装饰器

    python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...

  2. 十. Python基础(10)--装饰器

    十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...

  3. [python基础]关于装饰器

    在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...

  4. Day11 Python基础之装饰器(高级函数)(九)

    在python中,装饰器.生成器和迭代器是特别重要的高级函数   https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...

  5. 1.16 Python基础知识 - 装饰器初识

    Python中的装饰器就是函数,作用就是包装其他函数,为他们起到修饰作用.在不修改源代码的情况下,为这些函数额外添加一些功能,像日志记录,性能测试等.一个函数可以使用多个装饰器,产生的结果与装饰器的位 ...

  6. python基础-----函数/装饰器

    函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...

  7. python基础之装饰器(实例)

    1.必备 #### 第一波 #### def foo(): print 'foo' foo #表示是函数 foo() #表示执行foo函数 #### 第二波 #### def foo(): print ...

  8. 【Python基础】装饰器的解释和用法

    装饰器的用法比较简单,但是理解装饰器的原理还是比较复杂的,考虑到接下来的爬虫框架中很多用到装饰器的地方,我们先来讲解一下. 函数 我们定义了一个函数,没有什么具体操作,只是返回一个固定值 请注意一下缩 ...

  9. 学习PYTHON之路, DAY 5 - PYTHON 基础 5 (装饰器,字符格式化,递归,迭代器,生成器)

    ---恢复内容开始--- 一 装饰器 1 单层装饰器 def outer(func): def inner(): print('long') func() print('after') return ...

  10. Python基础之装饰器

    1.什么是装饰器? Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然 ...

随机推荐

  1. WIN7 X64的运行命令窗口

    要在WIN7系统下用界面的方式执行运行命令,则可以用如下两种方法方法打开运行对话框.1.点Win+R(run)就能出来的.2.在开始菜单上点右键,选“属性”,进入开始菜单属性设置界面,单击底部的“自定 ...

  2. python实现堆排序

    理论知识: 二叉树:度不超过2的树(节点最多有两个叉) 满二叉树:一个二叉树,如果每一个层的节点数都达到最大值,则这个二叉树就是满二叉树. 完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的 ...

  3. N Queen Again LightOJ - 1061

    N Queen Again LightOJ - 1061 首先预处理(或打表)出所有八皇后的解法(只有92种).然后枚举目标状态,对于每一个目标状态用一个状压dp求出到达那个状态的最小费用.到达任何一 ...

  4. Magic Numbers CodeForces - 628D

    Magic Numbers CodeForces - 628D dp函数中:pos表示当前处理到从前向后的第i位(从1开始编号),remain表示处理到当前位为止共产生了除以m的余数remain. 不 ...

  5. linux中用户组和用户

    linux中用户组和用户 1.介绍 在我们的linux系统,有很多用户组,也可以手动创建用户组,不同的用户组下面有很多的用户. 2.创建用户组及有关的命令 groupadd phpzu:创建一个php ...

  6. Android-apk文件反编译

    一:工具介绍及下载 1:apktool         作用:资源文件获取,可以提取出图片文件和布局文件进行使用查看 2:dex2jar       作用:将apk反编译成java源码(classes ...

  7. PHP多图片上传类推荐

    多文件上传是PHP中的一个基础应用,反正PHPer都会遇到的问题,现在就介绍一个功能完善.强大的多文件上传类给大家吧,能用上这个类的地方会很多. <?php class Upload{ var ...

  8. AJPFX总结Java 程序初始化过程

    觉得Core Java在Java 初始化过程的总体顺序没有讲,只是说了构造器时的顺序,作者似乎认为路径很多,列出来比较混乱.我觉得还是要搞清楚它的过程比较好.所以现在结合我的学习经验写出具体过程: 过 ...

  9. 使用kubeadm安装kubernetes v1.14.1

    使用kubeadm安装kubernetes v1.14.1 一.环境准备 操作系统:Centos 7.5 ​ ⼀ 一台或多台运⾏行行着下列列系统的机器器: ​ Ubuntu 16.04+ ​ Debi ...

  10. [转]Java中实现自定义的注解处理器

    Java中实现自定义的注解处理器(Annotation Processor) 置顶2016年07月25日 19:42:49 阅读数:9877 在之前的<简单实现ButterKnife的注解功能& ...