Python学习笔记:函数详解(下)
本文介绍:高阶函数,嵌套函数,以及由前面两个组成的装饰器
一、高阶函数:以下两种情况都是高阶函数
1、将函数名当成参数传递给另外一个函数(作用:不修改被传递函数源代码就可以添加新功能):
import time
def a():
time.sleep(1)
print("This is A funciton...")
# b函数相当于给a函数附加了一个计算时间的功能,但未修改a的源代码
def b(func):
print(func) # 打印func的内存地址
start_time = time.time()
func() # 调用a()
end_time = time.time()
print("a函数运行时间为:%s秒" % (end_time - start_time))
b(a) # 将a函数当成一个变量传递给b
2、将函数名当成返回值返回给另外一个函数(作用:不修改被传递函数调用方式就可以添加新功能):
import time
def a1():
time.sleep(1)
print("This is A1 funciton...")
# b1函数相当于给a1函数附加了一个计算时间的功能,但未修改a的源代码,也未修改a1的调用方式
def b1(func):
start_time = time.time()
func() # 调用a()
end_time = time.time()
print("a函数运行时间为:%s秒" % (end_time - start_time))
return func
a1 = b1(a1) # 将a1函数当成一个变量传递给b1
a1() # 调用未改变a1的调用方式,依然是a1()调用,只不过此时的a1已经通过b1装饰过了。
二、嵌套函数:在函数内部定义一个新的函数,注意:函数内部根据就近原则一层层往外寻找变量
x = 0
def grandpa():
x = 1
def dad():
x = 2
def son(): x = 3
print(x)
son()
dad()
grandpa()
三、装饰器:
1、定义:在不修改函数代码和调用方式的前提下对该函数实现新功能的编程范式,形式上是利用高阶和嵌套函数的特性,高阶函数 + 嵌套函数 = 装饰器,
所以装饰器本质上是一个未其他函数添加新功能的函数,而且不破坏原有代码。
2、原则:
a、不能修改被装饰函数的代码,此项可以防止修改以后对原来的程序逻辑造成影响
b、不能修改被修饰函数的调用方式,比如原来是test()这样调用的,不能改成test(参数1)或者改名成test2()调用,这也是为了让原来的旧代码逻辑不会出现问题导致程序运行失败。
c、综上所述,也就是说被装饰的函数感觉不到装饰器的存在,装饰器是透明的。 3、如何实现装饰器?
a、函数也是一个变量,函数名是变量名,函数执行体就是具体的函数值,所以将函数名赋值给别的函数,在别的函数内部就可以直接使用该函数。
b、单层装饰器:将函数名当成变量传递给另外一个函数,以达到装饰添加新功能的目的。
def timer(func):
def deco(*args,**kwargs): #这是一个嵌套函数,将*args和**kwargs可以允许外界传入任意个数的位置和关键词参数进来
start_time = time.time()
func(*args,**kwargs)
stop_time = time.time()
print("the func run time is %s" % (stop_time - start_time)) return deco @timer #@timer标签就相当于这句话 test1 = time(test1) 将test1函数变量名传给装饰器
def test1():
time.sleep(1)
print("This is test1") @timer # test2 = time(test2)
def test2(name,age):
time.sleep(2)
print("This is %s age:%d"%(name,age)) test1()
test2("test2",23) c、通过嵌套函数两层装饰器,可以让装饰器传递参数 def outside(arg_type):
def inside(func):
def deco(*args, **kwargs):
return_value = ""
if arg_type == "1":
print("加载功能1")
return_value = func(*args, **kwargs)
print("加载功能2")
elif arg_type == "2":
print("加载功能3")
return_value = func(*args, **kwargs)
print("加载功能4")
else:
return_value = func(*args, **kwargs)
print("加载功能5")
return return_value # 这个返回值可以让被装饰的func函数的返回值传到外面
return deco
return inside @outside(arg_type="1") # 在打标签装饰的同时,还可以传递参数给外层outside
def test1():
          print("This is test1")
          return "test1"
        @outside(arg_type="2")
        def test2():
            print("This is test2")
            return "test2"
        @outside(arg_type="3")
        def test3(1,2):
            print("This is test3")
            return "test3"
        # test1,test2和test3的的调用方式和其内部代码都未改变,但是通过装饰器却添加了新功能
        print(test1())
        print(test2())
        print(test3())												
											Python学习笔记:函数详解(下)的更多相关文章
- python基础之函数详解
		Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ... 
- Python内置函数详解
		置顶 内置函数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii https://docs.pyth ... 
- python pandas字符串函数详解(转)
		pandas字符串函数详解(转)——原文连接见文章末尾 在使用pandas框架的DataFrame的过程中,如果需要处理一些字符串的特性,例如判断某列是否包含一些关键字,某列的字符长度是否小于3等等 ... 
- Angular6 学习笔记——组件详解之模板语法
		angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ... 
- Angular6 学习笔记——路由详解
		angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ... 
- Angular6 学习笔记——组件详解之组件通讯
		angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ... 
- JavaScript学习笔记-实例详解-类(二)
		实例详解-类(二) //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ... 
- JavaScript学习笔记-实例详解-类(一)
		实例详解-类(一): //每个javascript函数(除了bind())都自动拥有一个prototype对象// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性const ... 
- Python学习笔记—函数
		函数 我们知道圆的面积计算公式为: S = πr2 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同大小的圆的面积: r1 = 12.34 r2 = 9.08 r3 = 73 ... 
- Android学习笔记-Dialog详解
		1.对话框的使用 1.1AlertDialog的显示 简单对话框以及监听的设置:重点掌握三个按钮(也就是三上单词): PositiveButton(确认按钮);NeutralButton(忽略按钮) ... 
随机推荐
- Flutter 拖拽排序组件 ReorderableListView
			注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 ReorderableListView是通过长按拖动某一项 ... 
- Nacos 数据持久化 mysql8.0
			一.问题描述 直接下载的稳定版本nacos编译后的文件,不支持mysql8及其以上版本,按照官网文档:https://nacos.io/zh-cn/docs/deployment.html 执行完成之 ... 
- 日常破解--XCTF easy_apk
			一.题目来源 来源:XCTF社区安卓题目easy_apk 二.破解思路 1.首先运行一下给的apk,发现就一个输入框和一个按钮,随便点击一下,发现弹出Toast验证失败.如下图所示: ... 
- 最简单的???ubuntu 通过crontab定时执行一个程序
			crontab在liunx系统中下载,我默认是认为下载安装了的.. crontab貌似只能在liunx系统中存在,如果是windows系统我不知道 创建一个名为jiaoben的文件夹存储sh文件,进入 ... 
- C++类的多态
			目录 一.静态多态 二.动态多态 三.虚函数 四.纯虚函数 五.C++ 接口(抽象类) 六.应用经验 七.版权声明 多态按字面的意思就是多种形态.当类之间存在层次结构,并且类之间是通过继承关联时,就可 ... 
- DataFrame简介(一)
			1. DataFrame 本片将介绍Spark RDD的限制以及DataFrame(DF)如何克服这些限制,从如何创建DataFrame,到DF的各种特性,以及如何优化执行计划.最后还会介绍DF有哪些 ... 
- burpsuit的安装和简单使用
			一.burpsuit的环境搭建 Burp Suite可以说是Web安全工具中的瑞士军刀,打算写几篇Blog以一个小白的角度去学习Burp Suite(简称BP),会详细地说一下的用法,说明一下每一个部 ... 
- Spring注解 - AOP 面向切面编程
			基本概念: AOP:Aspect Oriented Programming,即面向切面编程 指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式 前置通知(@Before):在目标 ... 
- table 上下左右 4根线的写法 :before :after 他们就能把td里面右下的那颗线给盖上 还有body和header横向滚动的联动 || 不能把body套在header上是为了上header表头固定 || 还有表头header的右侧overflow-y 是否出现滚动条的位置 记得有一个$nextTick 要不然会获取不到高度 高度就为0了 || 横向滚动条纵向滚动条
			table 上下左右 4根线的写法 <!--* @description 重点查核人员表!--><template> <div class="keyChecke ... 
- VS配置C++依赖包
			处理好三个东西 1.头文件,Configuration Properties → VC++ Directories → Include Directories 2.静态库,Configuration ... 
