python四大高阶函数_详谈Python高阶函数与函数装饰器(推荐)
一、上节回顾
Python2与Python3字符编码问题,不管你是初学者还是已经对Python的项目了如指掌了,都会犯一些编码上面的错误。我在这里简单归纳Python3和Python2各自的区别。
首先是Python3-->代码文件都是用utf-8来解释的。将代码和文件读到内存中就变成了Unicode,这也就是为什么Python只有encode没有decode了,因为内存中都将字符编码变成了Unicode,而Unicode是万国码,可以“翻译”所以格式编码的格式。Python3中str和bytes是两种格式,bytes可以当做二进制的表现形式。
Python2使用系统默认的字符编码解释代码,所以要用utf-8解释代码,就必须在头部申明;并且Python2中有解码和编码,但是解码动作是必须的而编码动作可以忽略,因为Python代码加载到内存中就是Unicode,这一点和python3一样;Python2中还需要注意的就是str和bytes是一个意思。Python2 里面的str就是Python3中的bytes格式,而Python3中的str其实就是Unicode.
函数基础(这里我就是用递归函数中的二分查找)
为什么使用函数:将将程序进行模块设计
定义函数有三种形式:
- 无参函数
- 有参函数
- 空函数
PS:如果函数有多个返回值,那么返回的来的数据格式是元组
- 如何在函数传入参数时限定参数数据格式。
def leon(x:int,y:int)->int:
pass
其中这里指定了x,y都必须是int类型 " -> "的意思是函数返回值也必须是int类型
print(yan.__annotations__):显示形参的限定数据格式以及返回值的格式
a = [1,2,3,4,5,7,9,10,11,12,14,15,16,17,19,21] #形参中的num
def calc(num,find_num):
print(num)
mid = int(len(num) / 2) #中间数的下标
if mid == 0: #递归函数非常重要的判断条件
if num[mid] == find_num:
print("find it %s"%find_num)
else:
print("cannt find num")
if num[mid] == find_num: #直接找到不用递归,结束函数
print("find_num %s"%find_num)
elif num[mid] > find_num: #find_num应该在左边,向下递归
calc(num[0:mid],find_num)
elif num[mid] < find_num: #find_num应该在右边,向下递归
calc(num[mid+1:],find_num)
calc(a,12)
匿名函数
c = lambda x:x+1 #x就是形参,c就是这个匿名函数的对象
print(c(22))
高阶函数-特性
1. 把一个函数的内存地址传给另外一个函数,当做参数
2.一个函数把另外一个函数的当做返回值返回
def calc(a,b,c):
print(c(a) + c(b))
calc(-5,10,abs) #引用上一节的实例,将-5和10绝对值相加
二、高阶函数(补充)
函数是第一类对象
函数可以被赋值
可以被当做参数
可以当做返回值
可以作为容器类型的元素
#函数可以被赋值
def leon():
print("in the leon")
l = leon
l()
#函数可以被当做参数
def yan(x): #这里x形参,其实就是我们调用实参的函数名
x() #运行函数
y = yan(leon)
#函数当做返回值
def jian(x): 和上面一样这这也必须传入一个函数
return x
j = jian(leon) #这里需要注意一点就是这里的意思是运行jian这个函数而这个函数返回的是x 也就是leon这个函数的内存地址,也就是说这时候leon这个函数并没有被执行
j() #运行 leon函数
#可以做为容器类型的元素
leon_dict = {"leon":leon}
leon_dict["leon"]() #这样也可以运行leon这个函数
三、闭包函数
1.什么是闭包?我来看一下,比较官网的概念(这不是我在官网上面找的,不过没有关系,反正你们也看不懂):
闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,闭包是由函数和与其相关的引用环境组合而成的实体。
懵逼了?不存在的。下面我用简洁的说一下,但是有一点很重要,闭包是装饰器中的重点,如果没有把闭包正真理解,那么学完装饰器之后会很快忘记。我们通过一个列子来说明下
import requests #首先导入一个模块,这个可以不用记
def get(url): #定义一个get函数里面需要传一个url的位置参数
def wapper(): #在定义一个wapper函数
res = requests.get(url) #这一步就是打开一个网页
return res.text #将网页以文字的形式返回
return wapper #返回最里层的wapper函数
g = get("http://www.baidu.com") #调用:首先因为作用域的原因,我们无法访问到里层的wapper函数,所以我们直接调用get函数这里返回了一个wapper函数
print(g()) # 然后我在调用g(get函数)的对象,这样是不是就访问到里层的wapper函数呢
PS:这里我们可以把函数当做一个特殊的变量,当代码从上向下执行的时候,如果函数不被调用话,函数内的代码是不会被执行的。就拿上面的上面的举例,当我们执行get函数的时候,这时候会返回一个wapper函数的内存地址,但是这个时候wapper函数并没有被执行也就是说g()这时候返回的状态其实就是wapper,这是我们只需要将g运行,就等于运行了wapper内的代码。
四、函数的嵌套调用
嵌套调用其实很好理解,就是在一个函数中调用另一个函数的结果,也就是return的东西,同样的我们看一段非常简单的代码来看一下。
#嵌套调用,在一个函数中调用另一个函数的功能
#calc这个函数就是在对比两个数字的大小
def calc2(x,y):
if x >y :
return x
else:
return y
#我靠老板非常变态,然你直接计算四个数字的大小,擦。
def calc4(a,b,c,d):
res1 = calc2(a,b) #res1的值,这里不就是calc2这个函数比较时最大的哪一个吗。
res2 = calc2(res1,c)
res3 = calc2(res2,d)
return res3
通过上面的代码我们做一记忆。什么时候会用到嵌套调用呢?很显然,就是我们这个函数(calc4)需要另外一个函数的实行结果(return的y或者x)。
五、装饰器(高级的闭包函数)
就拿下面的这段代码来说。如何在不改源代码的情况下实现计算代码的运行时间
def geturl(url):
response = requests.get(url)
print(response.status_code)
geturl(http://www.baidu.com)
def timer(func):
def wapper(url):
start_time = time.time()
func(url)
stop_time = time.time()
so_time_is = stop_time - start_time
print("运行时间%s"%so_time_is)
return wapper
@timer
def geturl(url):
response = requests.get(url)
print(response.status_code)
python = geturl(http://www.baidu.com)
图解代码
装饰器必备:
@timer就是装饰器,意思是装饰它下面的函数,而装饰器和被装饰的都是一个函数。
timer(装饰器函数),首先它会有一个位置参数(func)名字随意,但是必须并且只能是一个位置参数
func参数就是被装饰的geturl这个函数
为什么func是geturl这个函数呢-->上面写了一个装饰器功能:geturl=timer(geturl),我们看到这里的timer中传入的其实就是func函数所以func = geturl(被装饰的函数)
分析geturl=timer(geturl),首先我们可以得知timer这是一个闭包函数,当我们执行这个闭包函数,会把里层的函数(wapper)返回,也就是说timer(geturl)其实就是返回的wapper,所以就可以这样理解了geturl==wapper,所以当我们运行geturl的时候就相当于在执行wapper()这样的一个操作;如果这里实在记不住,就这样。咱上面不是有一个闭包函数吗?你就把geturl=timer(geturl)中的geturl(执行函数的返回结果)当做上面g(函数调用的返回结果),然后在分别再执行了下"g"或者"geturl”这个对象。
如果被装饰者有位置参数的话,我们需要在wapper函数中加上对应的位置参数用来接收,如果长度是不固定的话还可以用*args和**kwargs
六、有参装饰器
听着名字顾名思义,就是在装饰器中还有位置参数。
#一个low得不能再low得验证脚本,如果是显示环境中所有数据必须是由数据库或者一个静态文件提供,并且登录成功时,需要保存用户的一个状态
def auth(auth_type): #有参装饰器名称
def auth_deco(func): #定义第二层函数名称
def wrapper(*args,**kwargs): #最里层函数,主要实现认证功能
if auth_type == "file":
username = input("username>>:").strip()
password = input("username>>").strip()
if username == "leon" and password == "loveleon":
res = func(*args,**kwargs)
return res
elif auth_type == "mysql_auth":
print("mysql_auth...")
return func(*args,**kwargs)
return wrapper #第二层返回的是wrapper函数,其实就是home
return auth_deco #第一层返回的结果等于第二层函数的名称
@auth('file')
def home():
print("welcome")
home() #执行home-->wrapper
有参函数必备知识:
套路,通过上面无参装饰器,我们得出了geturl=timer(geturl)这个等式。回到有参装饰器,我们又会有什么样子的等式呢?首先@auth("file")是一个装饰器也就是一个函数,所以我们定义了一个auth(auth_type)这个函数,而这个函数返回的是什么呢?没有错就是第二层函数;到了这里我们就会发现@auth("file")其实就是@auth_deco,现在我们知道了现在装饰器其实就是auth_deco,那剩下的还不知道怎么写吗?
整理公式,auth('file')-----------(return)> auth_deco----->@auth_deco ->home=auth_deco(home)
如果记不住?如果实在是记不住,其实就可以这样理解,有参装饰器无非就是在无参装饰器上面加了一层(三层),然后在第一层返回了第二层的函数,而到了第二层就和我们普通用的装饰器是一毛一样了
七、模块导入
import ,创建一个leonyan.py的模块文件,等待被导入
a = 10
b = 20
c = 30
def read1():
print("in the read1")
def read2():
print("in the read2")
导入leonyan.py文件(调用模块文件和模块文件在同一目录下)
import leonyan #Python IDE这行会爆红,但是不用管
leonyan.read1() #执行leonyan这个包中的read1函数
leonyan.read2() #执行leonyan这个包中read2函数
print(leonyan.a + leonyan.b + leonyan.c ) #输出60
总结:在Python中包的导入(import ***)会干三个事情:1:创建新的作用域;2:执行该作用域的顶级代码,比如你导入的那个包中有print执行后就会直接在屏幕中输出print的内容;3:得到一个模块名,绑定到该模块内的代码
在模块导入的时候给模块起别名
import leonyan as ly
import pandas as pd #这是一个第三方模块,以后的博客中会写到,这是一个用于做统计的
给模块起别名还是挺多的,在有些模块的官方文档中,还是比较推荐这种方法的,比如pandas的官方文档中就是起了一个pd别名,总之as就是一个模块起别名
from *** import ***
from leonyan import read1 #引入直接调用
read1()
如果在调用模块的函数作用域中有相同的同名的,会将调用过来的覆盖。
在form ** import ** 中控制需要引用的变量(函数其实在未被执行的时候也是一个存放在内存中的变量)
from leonyan import read1,read2 在同一行中可以引用多个,只需要用逗号隔开就行了
print(read1)
print(read2)
#这里打印的就是read1和read2的内存地址
#需求我现在只需要导入read2
这时候我们就可以在leonyan这个函数中加上这么一行:
__all__ = ["read2"] #这里的意思就是别的文件调用为的时候用from ** import ** 只能拿到read2 这个函数的内存地址,也就是只有read2可以被调用
把模块当做一个脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
#fib.py
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
代码执行 Python flb.py 100
只需要简单了解的Python模块导入搜索路径
内建(build-in) --> sys.path(sys.path是一个列表,而且第一个位置就是当前文件夹)
模块导入的重点-->包的导入
在实际的开发环境中,你不可能一个文件的代码写到底,当然你也有可能会引用同文件夹中的其他模块,但是你有没有想过这一个项目不可能是你一个写的,都是很多人协作开发。这样就存在这样的一个问题了;不同的人不可能用一台电脑,也不可能在一个文件夹下面写写功能。他们也有自己的代码文件夹,然后大家把功能通过接口的方式,提供调用。这时候就面临这不同文件夹的调用问题。而这种问题也需要通过from ** import ** 调用。
上图中我运行“模块导入.py”这个文件夹,首先我from Pythonscript.leonyan.command import config,因为我们得运行脚本和需要导入的包都在Pythonscript的目录下面所以我直接通过绝对路径导入,然后一层一层“.”下去,知道最后import了这个config文件,这里我们需要注意一点:当脚本在最外层运行的时候sys.path 列表中的第一个参数就是运行脚本的目录,这是什么意思,这代表着你在别的包中有调用了其他的东西比如说我的config.py是调用了bing.py文件,这时候就必须写绝对路径,因为这在sys.path文件夹中已经找不到了,也就是导入不进来。
总结:包的导入其实都是很简单的,你需要记住一点:当你导入Python内建或者下载的第三方模块直接用import 导入,如果是自己写的就用from ** import ** 使用绝对目录导入就行了,也就是从调用脚本的上级目录开始导入。这样可以保证不会报模块导入的错误了。
以上这篇详谈Python高阶函数与函数装饰器(推荐)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
python四大高阶函数_详谈Python高阶函数与函数装饰器(推荐)相关推荐
- python装饰器功能是冒泡排序怎么做_传说中Python最难理解的点|看这完篇就够了(装饰器)...
https://mp.weixin.qq.com/s/B6pEZLrayqzJfMtLqiAfpQ 1.什么是装饰器 网上有人是这么评价装饰器的,我觉得写的很有趣,比喻的很形象 每个人都有的内裤主要是 ...
- python偏函数和高阶函数_【Python入门】8.高阶函数之 匿名函数和偏函数
目录 高阶函数 匿名函数 lambda 偏函数 高阶函数 匿名函数 lambda lambda,即希腊字母λ.顾名思义,匿名函数没有函数名,在运用时采取lambda x : ...的方式,如lambd ...
- python中递归函数的基例_详谈Python基础之内置函数和递归 Python递归和循环的区别...
Python 递归函数基例 2. 关于递归函数基例的说明,以下选项中错误的是 A 递归函数的基例决定所谓基例就是不需要递归就能求解的,一般来说是问题的最小规模下的解. 例如:斐波那契数列递归,f(n) ...
- python3_函数_形参调用方式 / 不定长参数 / 函数返回值 / 变量作用域 / 匿名函数 / 递归调用 / 函数式编程 / 高阶函数 / gobal和nonlocal关键字 / 内置函数
1.形参的调用方式 1. 位置参数调用 2. 关键词参数调用 原则: 关键词参数调用不能写在位置参数调用的前边 def test1(name, age):print("name:" ...
- python 微积分 函数_用Python学微积分(2)---复合函数
函数的复合(Composition) 定义:设函数y=f(u)和u=g(x)u=g(x),则函数y=f[g(x)]称为由y=f(u)和u=g(x)复合而成的复合函数,其中函数y=f(u)常常称为外函数 ...
- python里面的内置函数_【python】函数之内置函数
今天来介绍一下Python解释器包含的一系列的内置函数,下面表格按字母顺序列出了内置函数: 下面就一一介绍一下内置函数的用法: 1.abs() 返回一个数值的绝对值,可以是整数或浮点数等. print ...
- python对数据进行合并的函数_利用Python pandas对Excel进行合并的方法示例
前言 在网上找了很多Python处理Excel的方法和代码,都不是很尽人意,所以自己综合网上各位大佬的方法,自己进行了优化,具体的代码如下. 博主也是新手一枚,代码肯定有很多需要优化的地方,欢迎各位大 ...
- python一些常用函数_【python】常用的一些内置函数
1.cmp cmp(A,B)函数,比较A,B的大小,如果A大于B,返回1,A小于B返回-1,A等于B返回0 print cmp(12,33) >>>-1 print cmp(&quo ...
- python drop函数_用python帮财务小姐姐自动生成财务报表
↑↑↑关注后"星标"简说Python 人人都可以简单入门Python.爬虫.数据分析简说Python严选 来源:python数据分析之禅 作者:小dull鸟 One old w ...
最新文章
- keras 的 example 文件 neural_doodle.py 解析
- 静态移值编译的关键环境变量
- 用于区分IE的:条件注释
- 电子商务的五个技术研发方向
- 为什么BDLocationListener没有被调用
- HTML+CSS+JS实现 ❤️3D洞穴无限延伸动画特效❤️
- 安防监控必备的基础知识
- 2018-4-18 Linux学习笔记
- ubuntu 重设crontab -e的默认编辑器
- 对象流的序列化和反序列化
- Flex builder3相关
- ie和chrome浏览器下onproperty事件oninput onpropertychange的相应和相应属性的获取
- 身在国外,除了克服语言障碍,还得背好99乘法表
- 信息系统典型的开发架构
- matlab生成n阶O型方阵,matlab教程 06
- 中国计算机学会推荐中文科技期刊目录(2019年)
- vscode切换中英文
- 花式实现图片3D翻转效果
- 【我们为什么用高斯机制?】差分隐私代码实现系列(七)
- 噪音恐惧症_比恐惧强:公开的心理健康
热门文章
- 页面间参数值传递含“%”的处理方法
- c++学习笔记之静态成员函数
- Python学习笔记:I/O编程
- jdbc获取结果行数_如何获取JDBC中的行数?
- [云炬创业管理笔记]第十章商业计划书答辩测试2
- 科大星云诗社动态20210120
- 科大星云诗社动态20210414
- 科大星云诗社动态20210816
- 二十、“安化辞骚千万卒,康吾故土祭吾躯”(2021.6.14)
- python模块的分类有哪些_python之模块分类(六)