一、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. grid - 隐式命名网格线名称

    1.隐式的指定网格线反向指定了隐式的网格区域名称,命名的网格区域隐式的命名了网格线名称. 指定网格区域会给网格区域边线添加隐式的网格线名称.这些网格线的命名是基于网格区域来命名,只是在网格区域名称的后 ...

  2. Windows两个网卡配置路由规则 同时访问内网和外网

    电脑上有两个网卡,一个有线一个无线,有线连局域网,无线连外网,虽然两个网都连着,但还是会出现访问不通的情况. 这就要求我们自己来配置路由规则,让内网的访问走内网的网卡,外网的访问走外网的网卡. 一.查 ...

  3. 好用好玩的Python包

    ujson 用C++实现的json解析器,速度飞快. prettytable 在控制台下使用表格展示数据 import prettytable t=prettytable.PrettyTable([' ...

  4. MATLAB 程序处理结果出现 NAN 问题

    1)0/0  或者说  任意常数/0  也就是0不能做分母. (nan出现的情况绝大部分是分母出现0了)   若分子为0的情况,(分母不为0),结果也应该是0而非 NAN. 2)如果是 无穷大比无穷大 ...

  5. 解决:Reading table information for completion of table and column names

    mysql -A不预读数据库信息(use dbname 更快)—Reading table information for completion of table and column names Y ...

  6. 转:一千行MYSQL 笔记

    原文地址: https://shockerli.net/post/1000-line-mysql-note/ /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ ...

  7. 同一个tomcat下面放多个项目 每个项目用不同的域名访问

    vim ./conf/server.conf <Host name=" appBase="/www/test1/webapps" ##这是war包存放的位置 unp ...

  8. Github上 10 个开源免费且优秀的后台控制面板(转)

    https://github.com/ant-design/ant-design-pro https://mp.weixin.qq.com/s/Hn6hI-ubGw6N16nFzPdVLA

  9. 快速开发项目,用到的工具:UI 设置利器 sketch

    需求设计: axaure8.0 tool: teambition/石墨.幕布. 接口管理tool(后端开发接口,pc,m,app使用) https://www.eolinker.com/#/ ui 设 ...

  10. SecureCRT自动上传文件python脚本

    本人在ubuntu下使用SecureCRT,上传文件习惯用rz命令.每次上传都弹对话框选择文件按确定后才上传,感觉很费力.最后自己摸索整理出一个脚本. 使用方法是,在[Script]菜单点[Run.. ...