吃透Python函数进阶嵌套等知识点

简介: 吃透Python函数进阶嵌套等知识点

目录


💟一、函数的嵌套和作用域链

👾函数的嵌套调用

👾函数的嵌套定义

👾函数的作用域链

👾nonlocal关键字

👾global关键字

💟二、函数名的本质

👾函数名就是内存地址

👾函数名可以被赋值

👾函数名可以作为容器类型的元素

👾函数名可以作为函数的返回值

👾函数名可以作为函数的参数

👾思考 

💟三、闭包

👾闭包函数的概念

👾闭包函数的判断方法

👾闭包嵌套

💟小结


💟一、函数的嵌套和作用域链

  • 👾函数的嵌套调用

def max2(x,y):
    m  = x if x>y else y
    return m

def max4(a,b,c,d):
    res1 = max2(a,b)
    res2 = max2(res1,c)
    res3 = max2(res2,d)
    return res3

ret = max4(1,2,4,3)
print(ret)

输出结果:
4

  • 👾函数的嵌套定义

def f1():
    print("in f1")
    def f2():
        print("in f2")

    f2()
f1()

输出结果:
in f1
in f2

def f1():
    def f2():
        def f3():
            print("in f3")

        print("in f2")
        f3()

    print("in f1")
    f2()


f1()

输出结果:
in f1
in f2
in f3

  • 👾函数的作用域链

a = 1
def outer():
    a = 5
    def inner():
        a = 2
        def inner2():
            nonlocal a
            a += 1
            print('inner2',a)
        inner2()
        print('##a##:',a)
    inner()
    print('**a**:',a)

outer()

print('全局:',a)

输出结果:
inner2 3
##a##: 3
**a**: 5
全局: 1

  • 👾nonlocal关键字

#nonlocal 只能用于局部变量,找上层中离当前函数最近一层的局部变量且外部必须有这个变量
#声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量
#对全局无效,在内部函数声明nonlocal变量之前不能再出现同名变量
#对局部也只是对最近一层有影响
def f1():
    a = 1
    def f2():
        nonlocal a
        a = 2
    f2()
    print('a in f1 : ',a)

f1()

输出结果:
a in f1 :  2

  • 👾global关键字

# 对于不可变数据类型 在局部可是查看全局作用域中的变量
# 但是不能直接修改
# 如果想要修改,需要在程序的一开始添加global声明
# 如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效

💟二、函数名的本质

  1. 👾函数名就是内存地址

  2. 👾函数名可以被赋值

  3. 👾函数名可以作为容器类型的元素

  4. 👾函数名可以作为函数的返回值

  5. 👾函数名可以作为函数的参数

def func():
    print(123)
func()
print(func)
# 函数名就是内存地址
# 函数名可以被赋值
func2 = func
func2()

#函数名可以作为容器类型的元素
l = [func,func2]
for i in l:
    i()
def func():
    print(123)

def wahaha(f):
    f()
    return f            #函数名可以作为函数的返回值
qqxing = wahaha(func)   #函数名可以作为函数的参数
qqxing()

输出结果:
123
<function func at 0x000001ADF9946280>
123
123
123
123
123

  • 👾思考 

如果我自己定义了一个input函数(作用:调用该函数就打印'在下周周ovo'),会不会与内置的input函数有冲突呢?

def input(a):
    print('在下周周ovo')

那么接下来的代码怎么运行呢?

def input(a):
    print('在下周周ovo')

def func():
    input('请输入')
    print(input)

func()

答案:


💟三、闭包

  • 👾闭包函数的概念

内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数\

函数内部定义的函数称为内部函数

由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!

如果函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?那就直接将函数名字作为返回值就好

def outer():
    a = 1
    def inner():
        print(a)    #内部函数调用了外部变量a
    return inner

inn = outer()
inn()

输出结果:
1

  • 👾闭包函数的判断方法

判断闭包函数的方法__closure__

当运行后,如果有cell的话,就表示是闭包函数。如果没有就不是。

#输出的__closure__有cell元素 :是闭包函数
def func():
    name = 'eva'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#输出的__closure__为None :不是闭包函数
name = 'egon'
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()

输出结果:
(<cell at 0x000001E935CB0FA0: str object at 0x000001E935CC2CB0>,)
eva
None
egon

  • 👾闭包嵌套

顾名思义是两个或以上的闭包函数嵌套在一起

def wrapper():
    money = 10
    def func():
        name = 'zhou'    
        def inner():
            print(name,money)    #引用了func()函数中name变量引用了wrapper()函数中money变量
        return inner
    return func

f = wrapper()
i = f()
i()

输出结果:
zhuo 10


💟小结

 #func(一个函数名)  --->>对应函数的内存地址
#函数名()---函数调用
#函数的内存地址----()函数的调用
# 作用域两种
# 全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域  ——globals()
# 局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域) ——#locals()globals() : 永远打印全局的名字
#locals()  : 输出什么 根据locals所在位置
#在代码中要尽量少定义全局变量,多使用返回值和接收返回值
#函数的嵌套:
        嵌套调用
        嵌套定义:定义在内部的函数无法直接在全局被调用
#函数名的本质:
        就是一个变量,保存了函数所在的内存地址
#闭包:
        内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
相关文章
|
6天前
|
Python
【python从入门到精通】-- 第五战:函数大总结
【python从入门到精通】-- 第五战:函数大总结
29 0
|
3天前
|
Python
Python之函数详解
【10月更文挑战第12天】
Python之函数详解
|
4天前
|
安全 Linux 数据安全/隐私保护
python知识点100篇系列(15)-加密python源代码为pyd文件
【10月更文挑战第5天】为了保护Python源码不被查看,可将其编译成二进制文件(Windows下为.pyd,Linux下为.so)。以Python3.8为例,通过Cython工具,先写好Python代码并加入`# cython: language_level=3`指令,安装easycython库后,使用`easycython *.py`命令编译源文件,最终生成.pyd文件供直接导入使用。
python知识点100篇系列(15)-加密python源代码为pyd文件
|
4天前
|
存储 数据安全/隐私保护 索引
|
5天前
|
网络协议 数据库连接 Python
python知识点100篇系列(17)-替换requests的python库httpx
【10月更文挑战第4天】Requests 是基于 Python 开发的 HTTP 库,使用简单,功能强大。然而,随着 Python 3.6 的发布,出现了 Requests 的替代品 —— httpx。httpx 继承了 Requests 的所有特性,并增加了对异步请求的支持,支持 HTTP/1.1 和 HTTP/2,能够发送同步和异步请求,适用于 WSGI 和 ASGI 应用。安装使用 httpx 需要 Python 3.6 及以上版本,异步请求则需要 Python 3.8 及以上。httpx 提供了 Client 和 AsyncClient,分别用于优化同步和异步请求的性能。
python知识点100篇系列(17)-替换requests的python库httpx
|
1天前
|
调度 Python
python知识点100篇系列(20)-python协程与异步编程asyncio
【10月更文挑战第8天】协程(Coroutine)是一种用户态内的上下文切换技术,通过单线程实现代码块间的切换执行。Python中实现协程的方法包括yield、asyncio模块及async/await关键字。其中,async/await结合asyncio模块可更便捷地编写和管理协程,支持异步IO操作,提高程序并发性能。协程函数、协程对象、Task对象等是其核心概念。
|
2天前
|
Java Python
> python知识点100篇系列(19)-使用python下载文件的几种方式
【10月更文挑战第7天】本文介绍了使用Python下载文件的五种方法,包括使用requests、wget、线程池、urllib3和asyncio模块。每种方法适用于不同的场景,如单文件下载、多文件并发下载等,提供了丰富的选择。
|
3天前
|
数据安全/隐私保护 流计算 开发者
python知识点100篇系列(18)-解析m3u8文件的下载视频
【10月更文挑战第6天】m3u8是苹果公司推出的一种视频播放标准,采用UTF-8编码,主要用于记录视频的网络地址。HLS(Http Live Streaming)是苹果公司提出的一种基于HTTP的流媒体传输协议,通过m3u8索引文件按序访问ts文件,实现音视频播放。本文介绍了如何通过浏览器找到m3u8文件,解析m3u8文件获取ts文件地址,下载ts文件并解密(如有必要),最后使用ffmpeg合并ts文件为mp4文件。
|
5天前
|
索引 Python
Python中的其他内置函数有哪些
【10月更文挑战第12天】Python中的其他内置函数有哪些
7 1
|
5天前
|
开发者 索引 Python
Python中有哪些内置函数
【10月更文挑战第12天】Python中有哪些内置函数
9 0