Python函数定义、匿名函数、嵌套函数、闭包、装饰器

函数核心理解

  • 函数也是对象,可以把函数赋予变量
  • 可以把函数当作参数,传入另一个函数中
  • 可以在函数里定义函数,函数嵌套
  • 函数的返回值也可以是函数对象,闭包

1. 函数定义

def name(param1, param2, ..., paramN):
statements
return/yield value # optional
  • def是可执行语句,函数直到被调用前,都是不存在的,当程序调用函数时,def语句才会创建一个新的函数对象,并赋予其名字

  • 主程序调用函数时,必须保证这个函数此前已经定义过,不然会报错

  • 在函数内部调用其他函数时,函数间哪个申明在前、哪个在后无所谓,只要保证调用时,所需的函数都已经声明定义

  • python不用考虑输入的数据类型,而是将其交给具体的代码去判断执行,这种行为称为多态。

  • python函数的参数可以设定默认值,可以指定数据类型

    def name(param1 = 0, param2: int, ..., paramN):

函数作用

  • 减少代码的重复性
  • 模块化代码

2. 嵌套函数

2.1 作用
  • 能够保证内部函数的隐私,内部的函数只能被外部函数所调用和访问,不会暴露在全局作用域
  • 合理使用,可以提高程序的运行效率
2.2 函数变量作用域
  • 局部变量:函数内部定义的,只在函数内部有效,一旦执行完毕,局部变量就会被回收,无法访问
  • 全局变量定义在整个层次上的,不能在函数内部随意修改全局变量的值,如要修改,加global关键字
  • 函数内部,局部变量和全局变量同名,局部变量会覆盖全局变量
  • 嵌套函数,内部函数可以访问外部函数定义的变量,但无法修改,如要修改,加nonlocal关键字
  • 内部函数的变量和外部函数变量同名,覆盖
MIN = 1 # 全局变量
MAX = 8
print(f"MIN={MIN},MAX={MAX}")
def f1():
global MIN # 使用global关键字 修改全局变量
MIN += 1
a = 5 # 局部变量
b = 1
print(f"MIN={MIN},a={a},b={b}")
def f2():
MAX = 9 # 局部变量与全局变量同名,局部变量会覆盖全局变量
nonlocal a # 使用nonlocal关键字 修改外部函数的变量
a += 1
b = 2 # 内部函数变量与外部函数变量同名,覆盖
print(f"MIN={MIN},MAX={MAX},a={a},b={b}")
f2() # 内部函数被外部函数调用 f1()
print(f"MIN={MIN},MAX={MAX}")
MIN=1,MAX=8
MIN=2,a=5,b=1
MIN=2,MAX=9,a=6,b=2
MIN=2,MAX=8

3. 闭包

3.1 特点
  • 和嵌套函数类似,只是,外部函数返回的是一个函数,而不是一个具体的值
  • 返回的函数通常赋予一个变量,这个变量可以在后面被继续执行调用
  • 可以简化程序的复杂度,提高可读性
3.2 实例
# 计算一个数的n次幂
def nth_power(exponent):
def exponent_of(base):
return base **exponent
return exponent_of # 返回一个函数 # 调用函数
square = nth_power(2)
print(square)
print(square(3))
<function nth_power.<locals>.exponent_of at 0x7f3120911b90>
9

4. 装饰器

4.1 形式和作用
  • @装饰器函数,等价于,原函数名=装饰器函数(原函数名)
  • 装饰器就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改,也就是扩展了原函数的功能
4.2 装饰器函数写法
# 简单装饰器
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper
# 带参数的装饰器
def my_decorator(func):
def wrapper(message):
print('wrapper of decorator')
func(message)
return wrapper
# 通用的带参数的装饰器
def my_decorator(func):
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
# 保留原函数的元信息,将原函数的元信息,拷贝到对应的装饰器函数里
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper @my_decorator
def greet(message):
print(message) greet('hello world') # 输出
wrapper of decorator
hello world # 类装饰器,依赖函数__call__()
class Count:
def __init__(self, func):
self.func = func
self.num_calls = 0 def __call__(self, *args, **kwargs):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kwargs) @Count
def example():
print("hello world") example() # 输出
num of calls is: 1
hello world
4.3 装饰器用法实例
  • 身份认证、日志记录
  • 测试某些函数的执行时间
import time
import functools def log_execution_time(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
res = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} took {(end - start) * 1000)} ms")
return res
return wrapper @log_execution_time
def calculate_similarity(items):
...
  • 缓存

    python中内置的LRU cache,@lru_cache,会缓存进程中的函数参数和结果,缓存满了之后,会删除访问时间最早的数据

  • 工作中,二次开发,在原来的需求基础上做优化,原逻辑不需要修改的化,只需增加新的业务场景的时候

5. 匿名函数

5.1 格式
lambda argument1, argument2,... argumentN : expression
  • 此表达式返回的是一个函数对象,用法举例
 # 计算一个数的平方
square = lambda x: x**2 # 返回一个函数对象
a = square(3) # 调用函数
print(a)
# 9
5.2 使用原则
  • lambda是一个表达式,不是一个语句,只能写成一行
  • 程序中需要使用一个函数完成一个简单的共嗯那个,并且该函数只调用一次
5.3 使用方式
  • 1.用在列表内部
# 计算列表0-9的数的平方
li = [(lambda x: x*x)(x) for x in range(10)]
print(li)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • 2.用作某些函数的参数
# 按列表中元组的第1个元素排序
lis = [(1, 20), (3, 0), (9, 10), (2, -1)]
lis.sort(key=lambda x: x[0])
print(lis)
[(1, 20), (2, -1), (3, 0), (9, 10)]
# 对一个字典,根据值进行由高到低的排序
d = {"mike": 10, "luck": 2, "ben": 30}
new_li = sorted(d.items(), key=lambda x: x[1], reverse=True) # 返回的是列表嵌套元组类型
new_d = dict(new_li)
print(d,'\n', new_li, '\n', new_d, sep='')
{'mike': 10, 'luck': 2, 'ben': 30}
[('ben', 30), ('mike', 10), ('luck', 2)]
{'ben': 30, 'mike': 10, 'luck': 2}
  • 3.数据清洗中,常用lambda函数

6. python函数式编程

6.1 概念
  • 指代码中每一块都是不可变的,都由纯函数的形式组成
  • 纯函数,是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出
6.2函数式编程的优缺点
  • 优点主要在于其纯函数和不可变的特性使程序更加健壮,易于调试和测试
  • 缺点主要在于限制多,难写
6.3 map()、filter() 和 reduce()函数
  • map(function, iterable),对序列中的每个元素都运用function这个函数,返回一个迭代器
# 对列表中的每个元素乘以2
li = [1, 2, 3, 4, 5]
new_list_1 = map(lambda x: x*2, li)
print(list(new_list_1)) # 将迭代器转换为列表
[2, 4, 6, 8, 10]
  • filter(function, iterable),对序列中的每个元素,都使用function判断,并返回True或者False,最后将返回True的元素组成一个新的可遍历的集合,返回迭代器类型
# 返回列表中能够整除2的元素
li = [1, 2, 3, 4, 5]
new_list_2 = filter(lambda x: x % 2 == 0, li)
print(list(new_list_2))
[2, 4]
  • reduce(function, iterable),规定有两个参数,表示对序列中的每个元素以及上一次调用后的结果,运用function进行计算,最后返回的是一个单独的数值
# 计算列表元素的乘积
from functools import reduce
li = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, li)
print(product)
120

一文搞懂Python函数(匿名函数、嵌套函数、闭包、装饰器)!的更多相关文章

  1. 一文搞懂Python Unittest测试方法执行顺序

    大家好~我是米洛! 欢迎关注我的公众号测试开发坑货,一起交流!点赞收藏关注,不迷路. Unittest unittest大家应该都不陌生.它作为一款博主在5-6年前最常用的单元测试框架,现在正被pyt ...

  2. 一文搞懂 Python 的模块和包,在实战中的最佳实践

    最近公司有个项目,我需要写个小爬虫,将爬取到的数据进行统计分析.首先确定用 Python 写,其次不想用 Scrapy,因为要爬取的数据量和频率都不高,没必要上爬虫框架.于是,就自己搭了一个项目,通过 ...

  3. 一文搞懂Python迭代器和生成器

    很多童鞋搞不懂python迭代器和生成器到底是什么?它们之间又有什么样的关系? 这篇文章就是要用最简单的方式让你理解Python迭代器和生成器! 1.迭代器和迭代过程 维基百科解释道: 在Python ...

  4. day20 Python 高阶函数,函数,嵌套,闭包 装饰器

    高阶函数定义 1.函数接收的参数是一个函数名 2.函数的返回值是一个函数名 3.满足上述条件任意一个都可以称之为高阶函数 一.函数的接收参数是一个函数名 import time def foo(): ...

  5. Python四大神兽(迭代器&生成器&闭包&装饰器)

    一.迭代器 迭代是Python最强大的功能之一,是访问集合元素的一种方式.. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不 ...

  6. 一文搞懂Python可迭代、迭代器和生成器的概念

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  7. 一文搞懂Python中的所有数组数据类型

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  8. 基础篇|一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  9. 一文搞懂 Prometheus 的直方图

    原文链接:一文搞懂 Prometheus 的直方图 Prometheus 中提供了四种指标类型(参考:Prometheus 的指标类型),其中直方图(Histogram)和摘要(Summary)是最复 ...

随机推荐

  1. 关于adb的下载和基本使用

    我们无论是开发还是测试,对Android SDK一定都不陌生,如果我们要使用adb(Android debug bridge)命令,那么这个就必不可少了. 1.给大家提供一个下载地址:https:// ...

  2. session共享同步redis策略

    关于session共享的文章,网上很多,可是最关键的点我没有看到一篇.也就是session对象到底是怎么同步到redis的. spring-session底层原理到底是怎么样的一个同步更新策略,我没有 ...

  3. hadoop知识整理(5)之kafka

    一.简介 来自官网介绍: 翻译:kafka,是一个分布式的流处理平台.LinkedIn公司开发.scala语言编写.   1.支持流处理的发布订阅模式,类似一个消息队列系统: 2.多备份存储,副本冗余 ...

  4. 微信weixin://xxx 分析

    通过weixin://来打开微信客户端: <a href="weixin://">打开微信</a> <a href="weixin://dl ...

  5. CentOS 7 源码编译安装PostgreSQL 9.5

    下载 在postgresql的官方即可找到源码文件目录,地址如下:https://www.postgresql.org/ftp/source/,在下载列表中根据需求选择版本,进入子目录后,可以看到文件 ...

  6. .NET Core加解密实战系列之——RSA非对称加密算法

    目录 简介 功能依赖 生成RSA秘钥 PKCS1格式 PKCS8格式 私钥操作 PKCS1与PKCS8格式互转 PKCS1与PKCS8私钥中提取公钥 PEM操作 PEM格式密钥读取 PEM格式密钥写入 ...

  7. S7-1200视频教程: S7-1200的功能与特点-跟我做 - 2/112

    S7-1200视频教程: S7-1200的功能与特点-跟我做 - 2/112 观看连接: http://www.elearning.siemens.com.cn/video/Course/201105 ...

  8. java 基础 流程控制

    鄙人不才,基础不好,趁着闲时简单学习一下,仅作学习分享,如有不正确地方还请各位看客不吝指出. Java流程主要可以分为: 顺序(可以按照正常顺序一步步往下运行的) 选择(三元操作符[?:];if el ...

  9. 利用xampp集成环境搭建pikachu靶场及部分问题解决

    xampp的环境部署 1.本地服务器的搭建 首先要到官网下载xampp https://www.apachefriends.org/zh_cn/index.html 有各个不同的系统版本,这里我们选择 ...

  10. GitLab Runner部署(kubernetes环境)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...