nonlocal关键字

# 作用:将 L 与 E(E中的名字需要提前定义) 的名字统一

# 应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值

# 案例:

def outer():
   num = 10
   print(num)  # 10
   def inner():
       nonlocal num
       num = 20
       print(num)  # 20
   inner()
   print(num)  # 20

开放封闭原则:不改变调用方式与源代码上增加功能

'''
1.不能修改被装饰对象(函数)的源代码(封闭)
2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放)
'''

装饰器

# 把要被装饰的函数作为外层函数的参数通过闭包操作后返回一个替代版函数
# 被装饰的函数:fn
# 外层函数:outer(func) outer(fn) => func = fn
# 替代版函数: return inner: 原功能+新功能

def fn():
   print("原有功能")

# 装饰器
def outer(tag):
   def inner():
  tag()
       print(新增功能")
   return inner
fn = outer(fn)              
             
fn()

@语法糖: @外层函数

def outer(f):
   def inner():
  f()
       print("新增功能1")
   return inner
             
def wrap(f):
   def inner():
  f()
       print("新增功能2")
   return inner              

@wrap  # 被装饰的顺序决定了新增功能的执行顺序
@outer  # <==> fn = outer(fn): inner      
def fn():
   print("原有功能")

有参有返的函数被装饰

def check_usr(fn):  # fn, login, inner:不同状态下的login,所以参数是统一的
   def inner(usr, pwd):
       # 在原功能上添加新功能
       if not (len(usr) >= 3 and usr.isalpha()):
           print('账号验证失败')
           return False
       
       # 原有功能
       result = fn(usr, pwd)
       
  # 在原功能下添加新功能
       # ...
       
       return result
  return inner


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

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

"""
inner(usr, pwd):
  res = fn(usr, pwd) # 原login的返回值
  return res


login = check_usr(login) = inner

res = login('abc', '123qwe') # inner的返回值
"""

装饰器最终写法


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)

带参装饰器:了解

# 了解
def outer(input_color):
   def wrap(fn):
       if input_color == 'red':
           info = '\033[36;41mnew action\33[0m'
       else:
           info = 'yellow:new action'

       def inner(*args, **kwargs):
           pass
           result = fn(*args, **kwargs)
           print(info)
           return result
       return inner
   return wrap  # outer(color) => wrap


color = input('color: ')
@outer(color)  # @outer(color) ==> @wrap # func => inner
def func():
   print('func run')

func()

wraps修改函数文档注释

from functools import wraps
def outer(func):
   @wraps(func)
   def inner(*args, **kwargs):
       '''装饰器文档注释'''
       func(*args, **kwargs)
   return inner

@outer
def func(*args, **kwargs):
   '''原有文档注释'''
   print("原有功能")
print(func.__doc__)  #__doc__方法查看文档注释
 

登录认证功能

is_login = False  # 登录状态

def 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('登录成功')
       is_login = True
   else:
       print('登录失败')
       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 sell():
   print('可以销售')

home()

day 12 装饰器的更多相关文章

  1. Day 12 装饰器,开发封闭.

    一.什么是装饰器 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事务 ...

  2. python 基础篇 12 装饰器进阶

    本节主要内容:1. 通⽤装饰器回顾2. 函数的有⽤信息3. 带参数的装饰器4. 多个装饰器同时装饰⼀个函数 ⼀. 通⽤装饰器的回顾开闭原则: 对增加功能开放. 对修改代码封闭装饰器的作⽤: 在不改变原 ...

  3. 12装饰器及*args,**kwargs

    注:参数和返回值都是一个函数. 1,无参数 def decotare1(func): def wrapper(): print("First") func() return wra ...

  4. 函数与装饰器Python学习(三)

    1.1 文件处理 1.1.1 打开文件过程 在Python中,打开文件,得到文件句柄并赋值给一个变量,默认打开模式就为r f=open(r'a.txt','w',encoding='utf-8') p ...

  5. 详解python三大器——迭代器、生成器、装饰器

    迭代器 聊迭代器前我们要先清楚迭代的概念:通常来讲从一个对象中依次取出数据,这个过程叫做遍历,这个手段称为迭代(重复执行某一段代码块,并将每一次迭代得到的结果作为下一次迭代的初始值). 可迭代对象(i ...

  6. python文章装饰器理解12步

    1. 函数 在python中,函数通过def关键字.函数名和可选的参数列表定义.通过return关键字返回值.我们举例来说明如何定义和调用一个简单的函数: def foo(): return 1 fo ...

  7. day 12 - 1 装饰器进阶

    装饰器进阶 装饰器的简单回顾 装饰器开发原则:开放封闭原则装饰器的作用:在不改变原函数的调用方式的情况下,在函数的前后添加功能装饰器的本质:闭包函数 装饰器的模式 def wrapper(func): ...

  8. 转载 12步轻松搞定python装饰器

    作者: TypingQuietly 原文链接: https://www.jianshu.com/p/d68c6da1587a 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定pyt ...

  9. http://python.jobbole.com/85056/ 简单 12 步理解 Python 装饰器,https://www.cnblogs.com/deeper/p/7482958.html另一篇文章

    好吧,我标题党了.作为 Python 教师,我发现理解装饰器是学生们从接触后就一直纠结的问题.那是因为装饰器确实难以理解!想弄明白装饰器,需要理解一些函数式编程概念,并且要对Python中函数定义和函 ...

随机推荐

  1. cmake安装配置及入门指南

    前言 今天,从github下载代码学习,让我用cmake编译,纳尼?make我知道,cmake是啥鬼?天啊,无知很可怕!赶紧mark一波,虽然很耽误学习进度,但感觉还是要get一波! 一.安装准备 感 ...

  2. 行为驱动:Cucumber + Selenium + Java(一) - 环境搭建

    1.1 什么是行为驱动测试 说起行为驱动,相信很多人听说过. 行为驱动开发-BDD(Behavior Driven Development)是一个诞生于2003年的软件开发理念.其关键思想在于通过与利 ...

  3. 【API知识】一种你可能没见过的Controller形式

    前言 这里分享一下我遇到的一个挺有意思的Controller形式,内容涉及@RequestMapping注解的原理. 实际案例 一.基本描述 项目甲中有多个模块,其中就有模块A和B.(这里的模块指的是 ...

  4. 三种方法实现CSS三栏布局

    本文由云+社区发表 作者:前端林子 本文会分别介绍三种CSS实现三栏布局的方法,可在浏览器中打开查看效果 1.方法一:自身浮动的方法 实现方法:需要左栏向左浮动,右栏向右浮动,中间设左右margin来 ...

  5. [十六]基础类型BigInteger简介

        BigInteger和BigDecimal都是Java针对大数提供的类 超出了java的表示范围   属性简介 借助于signum和mag 来实现数据的符号位和实际数据的保存 final in ...

  6. JVM(一)史上最佳入门指南

    提到Java虚拟机(JVM),可能大部分人的第一印象是"难",但当让我们真正走入"JVM世界"的时候,会发现其实问题并不像我们想象中的那么复杂.唯一真正令我们恐 ...

  7. SpringBoot整合系列-整合SpringMVC

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9984607.html SpringBoot整合Spring MVC 步骤 第一步:添加必 ...

  8. 微信小程序组件minui在mac系统的使用注意事项

    1.mac系统使用npm 安装组件的时候,一定要注意mac系统的终端一定要用root用户操作. 具体的命令如下:sudo -i,然后提示输入系统的密码就进入了root操作用户. 2.然后就根据minu ...

  9. Java开发笔记(六十四)静态方法引用和实例方法引用

    前面介绍了方法引用的概念及其业务场景,虽然在所列举的案例之中方法引用确实好用,但是显而易见这些案例的适用场合非常狭窄,因为被引用的方法必须属于外层匿名方法(即Lambda表达式)的数据类型,像isEm ...

  10. Spring事务事件监控

    前面我们讲到了Spring在进行事务逻辑织入的时候,无论是事务开始,提交或者回滚,都会触发相应的事务事件.本文首先会使用实例进行讲解Spring事务事件是如何使用的,然后会讲解这种使用方式的实现原理. ...