博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数和常用模块1 装饰器
阅读量:5010 次
发布时间:2019-06-12

本文共 4628 字,大约阅读时间需要 15 分钟。

主要内容

  1. 装饰器的定义
  2. 装饰器的重要性
  3. 装饰器的原则
  4. 装饰器理解以及操作

装饰器的定义

本质是函数。(装饰其他函数) 它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。

装饰器的重要性

比如:已经上线的生产环境上有100个函数,需要增加新功能,新增功能不能修改源代码,也不能修改原函数的,这个时候就用到了装饰器。

装饰器经常有切面需求的场景,比如:插入日志,性能测试,事务处理,缓存,权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。 概括的讲,装饰的作用就是为已经存在的对象添加额外的功能。

例子:

import timedef timmer(func): def warpper(*args,**kwargs): start_time = time.time() func() stop_time = time.time() print('the func run time os %s' %(stop_time-start_time)) return warpper() @timmer def test1(): time.sleep(3) print('in the test1') test1()

装饰器的原则

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

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

  3. 不修改返回结果.

装饰器都函数来说是透明的。

装饰器理解以及操作

函数即“变量”

def test():        pass

相当于将函数体赋值给test的变量。 变量直接调用变量名,函数是函数名调用 test='函数体' test()

例子1:

将foo()函数体放入房间,然后通过foo()这个门牌号调用函数体,函数体按顺序执行, 当执行到bar()时候,没有门牌号对应。

例子2:

def bar():     print('in the bar') def foo(): print('in the foo') bar() foo() ####### def foo(): print('in the foo') bar() def bar(): print('in the bar') foo()

上面两个时没有区别的,上面即可正常执行。 函数先定义后调用。调用之前已经解释器解释过了。就能调用成功。 将def bar() def foo()看成函数体。

高阶函数

  1. 把一个函数名当做实参转给另外一个函数 (在不修改被装饰函数源代码的情况下为其添加功能)。

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

  3. 例子. 把一个函数名当做实参转给另外一个函数

bar 相当于门牌号,调用内存地址。

import timedef bar():    time.sleep(3) print('in the bar') def test1(func): start_time = time.time() func() #run bar stop_time = time.time() print('the func run time is %s' %(stop_time-start_time)) test1(bar) 运行结果: in the bar the func run time is 3.0036139488220215

相对于装饰器,调用方式被改变了,这要是在生产环境上功能上是不允许的。

  1. 返回值中包含函数名 例如:
import timedef bar():    time.sleep(3) print('in the bar') def test2(func): print(func) return func #print(test2(bar)) t=test2(bar) t() bar=test2(bar) bar() 运行结果: 
in the bar
in the bar

没有改变调用方式。

嵌套函数

顾名思义就是函数里面套函数。 函数嵌套,在一个函数体内用def定义而不是调用另外一个函数。

例如:

def foo():    print('in the foo') def bar(): print('in the bar') bar() foo() 运行结果: in the foo in the bar

局部作用域和全局作用域

在函数外,一段代码最始开所赋值的变量,它可以被多个函数引用,这就是全局变量; 在函数内定义的变量名,只能被函数内部引用,不能在函数外引用这个变量名,这个变量的作用域就是局部的,也叫它为局部变量;

如果函数内的变量名与函数外的变量名相同,也不会发生冲突。好比下面这种情况:

x =0def  grandpa(): x=1 def dad(): x=2 def son(): x=3 print(x) son() dad() grandpa() 运行结果为: 3

x = 0这个赋值语句所创建的变量X,作用域为全局变量; x = 3这个赋值语句所创建的变量X,它的作用域则为局部变量,只能在函数son()内使用。

x = 2这个赋值语句所创建的变量X,它的作用域则为局部变量,只能在函数dad()内使用。

x = 1这个赋值语句所创建的变量X,它的作用域则为局部变量,只能在函数grandpa()内使用。

尽管这两个变量名是相同的,但它的作用域为它们做了区分。作用域在某种程度上也可以起到防止程序中变量名冲突的作用,但如果做为玩蛇网python初学者来说,尽量避免这种情况发生比较好。

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

简单装饰器例子

@语法糖

import timedef timer(func): #timer(test1) func=test1 def deco(): start_time = time.time() func() stop_time = time.time() print('the func run time %s' % (stop_time - start_time)) return deco @timer #timer(test1) func=test1 def test1(): time.sleep(3) print('in the test1') @timer def test2(): time.sleep(3) print('in the test2') #test1=timer(test1) #返回的是deco的内存地址 test1() #相当于运行test1 #test2=timer(test2) #返回的是deco的内存地址 test2() #相当于运行test2 运行结果: in the test1 the func run time 7.023896217346191 in the test2 the func run time 7.066271066665649

传参数的装饰器例子

import timedef timer(func): #timer(test1) func=test1 def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print('the func run time %s' % (stop_time - start_time)) return deco @timer #test1= timer(test1) def test1(): time.sleep(3) print('in the test1') @timer #test2=timer(test2) = deco test2(name)=deco(name) def test2(name,age): print('test2', name,age) test1() test2('cathy',22) 运行结果: in the test1 the func run time 3.003638982772827 test2 cathy 22 the func run time 3.409385681152344e-05

用户验证场景装饰器

#!/usr/bin/env python# -*- coding:utf-8 -*-# Author:Cathy Wuuser,passwd='cathy','abc123' def auth(auth_type): print('auth fucn:',auth_type) def outer_warpper(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('\033[32;1m User has passed authenticaiton\033[0m') res = func(*args, **kwargs) print('after authenticaiton') return res else: exit('\033[32;1m Invalid passwodr or username\033[0m') elif auth_type == 'ldap': print('ldap authenticaiton') return wrapper return outer_warpper def index(): print('welcome to the index') @auth(auth_type='local') def home(): print('welcome to the home') return "from home" @auth(auth_type='ldap') def bbs(): print('welcome to the bbs') index() print(home()) bbs() 运行结果: auth fucn: local auth fucn: ldap welcome to the index wrapper func args: username:cathy password:abc123 User has passed authenticaiton welcome to the home after authenticaiton from home wrapper func args: ldap authenticaiton

参考网页

转载于:https://www.cnblogs.com/cathywu/p/7246054.html

你可能感兴趣的文章
创建和修改主键 (SQL)
查看>>
2018-2019 ICPC, NEERC, Southern Subregional Contest(训练记录)
查看>>
20145233 《信息安全系统设计基础》第7周学习总结
查看>>
linux设备驱动程序第3版学习笔记(例程2--hellop.c)
查看>>
玩转storm
查看>>
第10章 使用Apache服务部署静态网站
查看>>
关于给予webApp框架的开发工具
查看>>
c语言编写的生成泊松分布随机数
查看>>
Maven入门笔记
查看>>
iOS webView的常见属性和方法
查看>>
理解position:relative
查看>>
Codeforces Round #344 (Div. 2) Messager KMP的应用
查看>>
20145308刘昊阳 《Java程序设计》第4周学习总结
查看>>
js倒计时
查看>>
EasyUI datagrid 格式 二
查看>>
Android虹软人脸识别sdk使用工具类
查看>>
UI:基础
查看>>
浅谈 @RequestParam 和@PathVariable
查看>>
设计模式之---装饰器设计模式
查看>>
基于WordNet的英文同义词、近义词相似度评估及代码实现
查看>>