一、nonlocal关键词

1、作用:将local和enclosing(e中的名字需要提前定义)中的名字统一

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

3、案例

def outer():
num = 0
print(num) # 结果为 0
def inner(): # 如果想在被嵌套的函数中修改外部函数变量(名字)的值
nonlocal num # 将L与E(E中的名字需要提前定义)的名字统一
num = 100
print(num) # 结果为 100
inner()
print(num) # 结果为 100
outer()
num =100
def fn():
global num
num = 10
def fn2():
global num
num = 20
fn2()
fn()
print(num)

二、开放封闭原则

1、定义:不能修改源代码,不能更改调用方式,但可以对外提供增加新功能的特性

2、开放:修改了源代码,没有更改调用方式,对外调用方式还是原来的,但功能有所增加,不能更改被装饰对象(函数)的调用方式,且达到了增加功能的效果

def fn():
print('fn run1')
print('fn run')
print('fn run3')
fn()

3、封闭:没有修改源代码,但更改了调用方式 。

不能修改被被装饰对象(函数)的源代码

def fn():
print('fn run')
fn()
def wrap(fn):
print('fn run1')
fn()
print('fn run3')
fn()
wrap(fn)

三、装饰器

1、装饰器:闭包的一个应用场景。为一个函数添加新功能的工具

def vase():
print('插花')
vase() # 结果为 插花 # 增加一个绘画观赏功能:不满足封闭开放原则,修改了源代码
def vase():
print('插花')
print('绘画观赏')
vase()
# 结果为
# 插花
# 绘画观赏 # 增加一个绘画观赏功能,不满足开放封闭原则,更改了调用方式
def vase():
print('插花')
vase()
def wrap(vase):
vase()
print('绘画观赏')
wrap(vase)
def vase():
print('插花') def wrap(vase):
def fn():
print('绘画观赏')
return fn
vase = wrap(vase)
vase()
def vase():
print('插花') # 下方的函数嵌套结构就是装饰器*****
def wrap(x): #x=vase
def fn():
x() # 原有的vase
print('绘画:进行观赏')
return fn # 拓展功能后的vase
vase = wrap(vase) # 将拓展功能后的功能函数重新赋值给vase
vase() # 功能拓展了,且调用方式不变

2、装饰器简化语法

def outer(fn):
def inner():
fn()
print('绘画观赏')
return inner
def wrap(fn):
def inner():
fn()
print('摆放功能')
return inner
# 语法糖|笑笑语法
@wrap # 总结:一个函数可以被任意一个装饰器装饰,也可以被任意几个装饰器装饰
@outer # 装饰的顺序会影响新增功能的执行顺序 def vase():
print('插花')
vase()
# 结果为
# 插花
# 绘画观赏
# 摆放功能

四、有参有反的函数被装饰

案例

# 增加一个账号处理功能: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 # login = check_usr(login) = inner
@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)

五、登录认证案例

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()

五、案例

1、写出完整的装饰器(不用考虑带参装饰器,就是普通装饰器)语法

def wrapper(func):
def inner(*args, **kwargs):
pass
result = func(*args, **kwargs)
pass
return result
return inner

2、有一个计算两个数和的方法,为其添加一个确保两个参数都是int或float类型的装饰器,保证运算不会抛异常

def check_num(func):
def inner(n1, n2):
b1 = isinstance(n1, int) or isinstance(n1, float)
b2 = isinstance(n2, int) or isinstance(n2, float)
if not (b1 and b2):
print('不能求和')
return # 结束掉,不让其进入计算功能
return func(n1, n2)
return inner @check_num
def add(n1, n2):
return n1 + n2 print(add(1, ''))

3、有一个一次性录入人名并返回人名的方法(人名只考虑存英文),为其添加一个装饰器,使得处理后人名首字母一定大写

def upper_name(func):
def inner():
result = func()
return result.title() # Owen
return inner @upper_name
def get_name():
name = input('name: ') # owen
return name print(get_name())

day12 十二、开放封闭、装饰器的更多相关文章

  1. 十二、Decorator 装饰器模式

    设计: 代码清单: Display public abstract class Display { public abstract int getColumns(); public abstract ...

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

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

  3. Python小白学习之路(二十四)—【装饰器】

    装饰器 一.装饰器的本质 装饰器的本质就是函数,功能就是为其他函数添加附加功能. 利用装饰器给其他函数添加附加功能时的原则: 1.不能修改被修饰函数的源代码        2.不能修改被修饰函数的调用 ...

  4. Python小白学习之路(二十五)—【装饰器的应用】

    通过一个任务来加深对装饰器的理解和应用 回顾:装饰器的框架 def timmer(func): def wrapper(): func() return wrapper 任务:给以下正在运行的程序加一 ...

  5. python学习 day12 (3月18日)----(装饰器内置函数)

    读时间函数: # import time # def func(): # start_time = time.time() # 代码运行之前的时间 # print('这是一个func函数') # ti ...

  6. python 二——函数、装饰器、生成器、面向对象编程(初级)

    本节内容 1.函数 2.装饰器 3.生成器 4.类 一.函数 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 函数式 ...

  7. python入门(十五):装饰器

    1.装饰器(decorator):设计模式 作用:给不同的函数和方法,增加不同的公用的功能. @classmethod,@staticmethod等均是装饰器 定义一个装饰函数,函数必须返回一个闭包函 ...

  8. python二 总结--函数-- 装饰器

    装饰器是什么? 有什么用? 为什么要用? 真的有用吗? 1.装饰器: 装饰器: 定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能. 原则:1.不能修改被装饰的函数的源代码          ...

  9. (二)Python 装饰器

    1. 函数 在 Python 中,使用关键字 def 和一个函数名以及一个可选的参数列表来定义函数.函数使用 return 关键字来返回值.定义和使用一个最简单的函数例子: >>> ...

随机推荐

  1. 【PMP】关键路径法与关键链法

    通俗理解 关键路径法:把项目上的资源都事先全部分到每个活动上. 关键链法:每个活动不打富余,项目经理自己掌握资源,哪个成员执行过程中遇到困难,再给他单独分配资源. PMBOK定义 关键路径法:关键路径 ...

  2. 如何在VMware8虚拟机里安装Xp GHOST系统 解决不能启动Xp系统方法

    好久没有装系统了.之前直接在硬盘中装,装个xp(c盘内).win7(d盘内).centos(虚拟机内)三系统同在一台笔记本电脑上.走了点弯路,这次记录下在虚拟机内装ghost xp. 安装步骤: 1. ...

  3. c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习

    c#中@标志的作用   参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...

  4. Effective Java 第三版——88. 防御性地编写READOBJECT方法

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  5. Git Flow 分支管理简述

    概述 Git 是什么 Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的 ...

  6. xml序列化与反序列化工具

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  7. [C++]Qt程式异常崩溃处理技巧(Win)

    文章转载来自     http://www.cnblogs.com/lcchuguo/p/5177715.html     作者 lcchuguo https://blog.csdn.net/baid ...

  8. 下载Chrome商店和Youtube资源

    下载chrome浏览器插件 站点:http://cooal.cn/crx.php 操作步骤: 1.打开扩展介绍页面 (在 三道杠图标>工具>扩展程序 里相应扩展的"访问网站&qu ...

  9. [mvc] 过滤器filter一览

    1.mvc的过滤器种类

  10. python pyenv

    使用pyenv安装多个版本的python 管理多个python环境使用 virtualenv 请看  http://www.cnblogs.com/juandx/p/5357518.html 安装py ...