python基础——8(装饰器)
一、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(装饰器)的更多相关文章
- python基础—函数装饰器
python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...
- 十. Python基础(10)--装饰器
十. Python基础(10)--装饰器 1 ● 装饰器 A decorator is a function that take a function as an argument and retur ...
- [python基础]关于装饰器
在面试的时候,被问到装饰器,在用的最多的时候就@classmethod ,@staticmethod,开口胡乱回答想这和C#的static public 关键字是不是一样的,等面试回来一看,哇,原来是 ...
- Day11 Python基础之装饰器(高级函数)(九)
在python中,装饰器.生成器和迭代器是特别重要的高级函数 https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...
- 1.16 Python基础知识 - 装饰器初识
Python中的装饰器就是函数,作用就是包装其他函数,为他们起到修饰作用.在不修改源代码的情况下,为这些函数额外添加一些功能,像日志记录,性能测试等.一个函数可以使用多个装饰器,产生的结果与装饰器的位 ...
- python基础-----函数/装饰器
函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...
- python基础之装饰器(实例)
1.必备 #### 第一波 #### def foo(): print 'foo' foo #表示是函数 foo() #表示执行foo函数 #### 第二波 #### def foo(): print ...
- 【Python基础】装饰器的解释和用法
装饰器的用法比较简单,但是理解装饰器的原理还是比较复杂的,考虑到接下来的爬虫框架中很多用到装饰器的地方,我们先来讲解一下. 函数 我们定义了一个函数,没有什么具体操作,只是返回一个固定值 请注意一下缩 ...
- 学习PYTHON之路, DAY 5 - PYTHON 基础 5 (装饰器,字符格式化,递归,迭代器,生成器)
---恢复内容开始--- 一 装饰器 1 单层装饰器 def outer(func): def inner(): print('long') func() print('after') return ...
- Python基础之装饰器
1.什么是装饰器? Python的装饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然 ...
随机推荐
- Robot Framework操作mongodb数据库
RF对mongodb操作需要安装以下两个库: 1.pymongo 可以采用pip install pymongo: (如果下载过慢,可指定下载源,如:http:pypi.douban.com/simp ...
- [NOIP2018校模拟赛]T2矩阵分组 Matrix
题目链接: 矩阵分组 分析: 这道题求的是两部分极差当中大的那个的最小值.对于这种求最值的问题,我们很自然(其实并没有)地想到二分答案. 这个题有两个结论: (好像当时看出来了第一个?然后发现下面都不 ...
- 莫比乌斯函数 && HDU-1695
莫比乌斯函数定义: $$\mu(d)=\begin{cases}1 &\text{d = 1}\\(-1)^r &\text{$d=p_1p_2...p_r,其中p_i为不同的素数$} ...
- UIBarButtonItem系统默认风格形状
typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) { UIBarButtonSystemItemDone, UIBarButtonSystemItem ...
- 转 Java 208道面试题及部分答案 补充部分答案
转自https://www.cnblogs.com/chen1005/p/10481102.html ---恢复内容开始--- 一.Java 基础 1.JDK 和 JRE 有什么区别? 答:JRE ...
- new操作符具体干了什么
function Func(){ }; var newFunc=new Func (); new共经过了4个阶段 1.创建一个空对象 var obj=new Object(); 2.设置原型链 把 o ...
- ArcGIS二次开发之读取遥感图像像素值的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 首先是读取遥感图像的R.G.B波段数据的做法.读取R.G.B波段数据的像素值主要通过IRaster接口的Read方法在 ...
- iOS 应用程序内部国际化,不跟随系统语言
前言:网络上关于iOS国际化的文章很多,但基本上都是基于跟随系统语言的国际化,笔者就不赘述了-0 – 今天要讲的是不跟随系统的切换语言版本方案,即程序内部的切换语言版本方案. 一.总则: 应用内部语言 ...
- mongodb的安装及配置安装服务
1. 安装mongodb数据库 mongodb官方网址:https://www.mongodb.org 安装好之后的步奏: 第一步:规划你的安装目录和数据库文件的存储路径,我打算将Mongo的程序文件 ...
- Javaweb学习笔记6—EL表达式与JSTL及自定义标签
今天来讲javaweb的第六阶段学习. EL表达式与JSTL及自定义标签是对上篇文章介绍的JSP的扩展,不能说是很重要的东西,但是也要了解. 老规矩,首先先用一张思维导图来展现今天的博客内容. ps: ...