首页 > 编程语言 >【3.0】Python高级之函数对象与闭包函数

【3.0】Python高级之函数对象与闭包函数

时间:2023-11-20 09:47:39浏览次数:33  
标签:闭包 __ return 函数 Python func def

【一】函数对象

  • 函数对象指的是函数可以被当做 数据 来处理,具体可以分为四个方面的使用

【1】函数可以被引用

# 定义一个函数
def add(x, y):
    return x + y


# 将函数地址绑定给一个变量
func = add
# 通过这个变量找到对应的地址,从而调用函数
res = func(1, 2)
print(res) # 3

【2】函数可以作为容器类型的元素

def add(x, y):
    return x + y


dic = {'add': add, 'max': max}
print(dic)  # {'add': <function add at 0x0000020523843E20>, 'max': <built-in function max>}
res = dic['add'](1, 2)
print(res)  # 3

【3】函数可以作为参数传入另外一个参数

def add(x, y):
    return x + y


def foo(x, y, func):
    return func(x, y)


res = foo(1, 2, add)
print(res) # 3

【4】函数的返回值可以是一个函数

def add(x, y):
    return x + y


def bar():
    return add


func = bar()
print(func)  # <function add at 0x00000239EC363E20>
res = func(1, 2)
print(res)  # 3

【二】闭包函数

【1】什么是闭包

  • 闭包是指包含对自由变量的函数和对这些变量的引用环境的组合。

  • 基于函数对象的概念,可以将函数返回到任意位置去调用

  • 但作用域的关系是在定义完函数时就已经被确定了的,与函数的调用位置无关。

# 定义全局变量
x_global = 1


# 定义外层函数
def outer():
    def inner():
        print(x_global)

    return inner


def func():
    x_func = 3
    # 调用f1()返回函数f2
    inner = outer()
    # 需要按照函数定义时的作用关系去执行,与调用位置无关
    inner()


func()  # 结果为1

【2】什么是闭包函数

  • 也就是说函数被当做数据处理时,始终以自带的作用域为准。
  • 若内嵌函数包含对外部函数作用域(而非全局作用域)中变量的引用
  • 那么该’内嵌函数’就是闭包函数,简称闭包(Closures)
# 定义全局变量
x_global = 1


def outer():
    # 定义局部变量,覆盖全局变量
    x_global = 2

    def inner():
        # 打印外部函数的局部变量
        print(x_global)

    return inner


func = outer()
func()  
# 结果为2

【3】如何查看闭包函数所包裹的外部变量

  • 可以通过函数的closure属性,查看到闭包函数所包裹的外部变量
# 定义全局变量
x_global = 1


def outer():
    # 定义局部变量,覆盖全局变量
    x_global = 2

    def inner():
        # 打印外部函数的局部变量
        print(x_global)

    return inner


func = outer()
func()
# 结果为2

res_first = func.__closure__
print(res_first)  # (<cell at 0x000001945A08B9A0: int object at 0x0000019459AA0110>,)

print(dir(func.__closure__[0]))
'''
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
'''

# __closure__ 属性是一个元组,包含了函数闭包中的每个 cell 对象。每个 cell 对象都有一个 cell_contents 属性,它存储着相应的值。
res_second = func.__closure__[0].cell_contents
print(res_second)  # 2
  • “闭”代表函数是内部的,“包”代表函数外’包裹’着对外层作用域的引用。
  • 因而无论在何处调用闭包函数,使用的仍然是包裹在其外层的变量。

【4】闭包函数用途

(1)保持状态

  • 保持状态: 闭包可以用来保持函数调用之间的状态。

  • 目前为止,我们得到了两种为函数体传值的方式

    • 一种是直接将值以参数的形式传入
    • 另外一种就是将值包给函数

[1]将值以参数的形式传入

import requests

# 将值以参数的形式传入
def get(url):
    return requests.get(url).text

[2]将值包给函数

import requests

# 将值包给函数
def page(url):
    def get():
        return requests.get(url).text

    return get

[3]对比

  • 方式一在下载同一页面时需要重复传入url
  • 方式二只需要传一次值,就会得到一个包含指定url的闭包函数,以后调用该闭包函数无需再传url
import requests


# 将值以参数的形式传入
def get(url):
    return requests.get(url).text


# 方式一下载同一页面
get('https://www.python.org')
get('https://www.python.org')
get('https://www.python.org')
import requests


# 将值包给函数
def page(url):
    def get():
        return requests.get(url).text

    return get


# 方式二下载同一页面
python = page('https://www.python.org')
python()
python()
python()

(2)函数工厂

  • 函数工厂: 闭包允许创建函数工厂,即可以动态生成函数。
  • 在你的例子中,page 函数就是一个函数工厂,它返回一个根据传入的 url 动态生成的函数。
import requests


# 将值包给函数
def page(url):
    def get():
        return requests.get(url).text

    return get

python = page('https://www.python.org')
java = page('https://www.java.com')

(3)封装

  • 封装: 闭包可以用来实现类似面向对象编程中的封装概念。
  • 通过将函数和其相关的状态(变量)捆绑在一起,形成一个封闭的单元。
def counter():
    count = 0

    def increment():
        nonlocal count
        count += 1
        return count

    return increment

counter1 = counter()
counter2 = counter()

print(counter1())  # 1
print(counter1())  # 2
print(counter2())  # 1

标签:闭包,__,return,函数,Python,func,def
From: https://www.cnblogs.com/dream-ze/p/17843226.html

相关文章

  • 【2.0】Python高级之名称空间与作用域
    【一】名称空间与闭包【1】什么是名称空间名称空间即存放名字与对象映射/绑定关系的地方。对于x=3Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中delx表示清除该绑定关系。在程序执行期间最多会存在三种名称空间【2】内建名称空间伴随pyt......
  • 【1.0】Python高级之函数
    【一】函数的基本使用基于前一部分的学习,我们已经能开发一些功能简单的小程序了但随着程序功能的增多,代码量随之增大此时仍不加区分地把所有功能的实现代码放到一起,将会使得程序的组织结构不清晰,可读性变差,且程序中需要频繁使用同一功能时,只能重复编写该功能的实现代码,日积月......
  • 创建Conda环境时,自动包含当前系统中的Python和CUDA等
    要在创建Conda环境时自动包含当前系统中的Python和CUDA,可以使用Conda的environment.yml文件。environment.yml文件是一个文本文件,其中包含了创建Conda环境所需的依赖项信息。下面是一个示例的environment.yml文件,其中包含了Python和CUDA的依赖项:yaml复制代码 name:myenv......
  • [oeasy]python001_先跑起来_python_三大系统选择_windows_mac_linux
    先跑起来......
  • Linux环境下Python3.10安装
    事件缘起我在Linux服务器(CentOS7.8)安装Python3.10,并替换python软链接为python3之后,yum命令不可用。特此记录一下。完整安装步骤如下:Python3.10安装1.使用yum程序提前安装Python依赖。yuminstallwgetzlib-develbzip2-developenssl-develncurses-develsqlite-develr......
  • 【Python进阶】近200页md文档14大体系知识点,第4篇:linux命令和vim使用
    本文从14大模块展示了python高级用的应用。分别有Linux命令,多任务编程、网络编程、Http协议和静态Web编程、html+css、JavaScript、jQuery、MySql数据库的各种用法、python的闭包和装饰器、mini-web框架、正则表达式等相关文章的详细讲述。全套Python进阶笔记地址:请移步这里共......
  • 11.19(函数)
    函数是什么?1.函数就是一个大型程序中某部分代码,由一个或多个模块组成。相较于其他代码,有一定的独立性。2.一般函数都有独立信函数的分类:a:函数库:C语言本身提供的函数b:自定义函数:体现的解决问题的能力函数的调用:传值调用  传址调用#include<stdio.h>#include<math.h>intis_p......
  • 【Python】【OpenCV】【NumPy】图像和原始字节的转换
    学习完基础的图像算法,开始接触OpenCV学习:灰度图中,一个像素点上的灰度级需要一个字节(byte,2^8,8bit)进行存储,此时的灰度图是二维的。而当我们需要转换为彩色图时,即三维,便会产生颜色通道(Channel),这个时候,一个像素点上的灰度级便会需要三个字节来进行存储。可以借助笛卡尔坐标系来帮助......
  • C++ merge()函数
    merge()函数用于将2个有序序列合并为1个有序序列,前提是这2个有序序列的排序规则相同(要么都是升序,要么都是降序)。并且最终借助该函数获得的新有序序列,其排序规则也和这2个有序序列相同。merge()函数支持自定义规则排序,merge()有两种语法格式//以默认的升序排序作为排......
  • Python装饰器-计算运行时间小例子
    importtimedefrun_time(func):"计算运行时长装饰器"defwrapper(*args,**kwargs):#包装函数start=time.time()#在调用装饰函数前干点事情res=func(*args,**kwargs)end=time.time()#在调用装饰函数后干点事情t=e......