Python基础教程:嵌套函数、闭包

枫铃3年前 (2021-09-30)Python246

嵌套函数

  • 在函数中定义另一个函数称为嵌套函数。
  • 嵌套函数可以访问包围范围内的变量。
def print_msg(msg):

    def printer():
        print(msg)

    printer()

print_msg("Hello")  

执行结果:

Hello

嵌套函数的调用

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def func1():
    print('func1')
 
    def func2():
        print('func2')
 
func1()

执行结果:

func1

为什么函数func2没有被执行?

任意一个函数定义完成之后,如果没有人通过名字调用它,就永远不会执行,如果需要执行可以按照如下方式进行调用:

def func1():
    print('func1')
 
    def func2():
        print('func2')
     
    func2()
 
func1()

执行结果:

func1
func2

nonlocal 关键字

内层函数改变外层函数变量用nonlocal, nonlocal不能定义新的外层函数变量,只能改变已有的外层函数变量,同时nonlocal不能改变全局变量。
不加nolocal关键字

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def outer():
    a = 1

    def inner():
        a += 1
        print("Inner", a)

    inner()
    print("Outer", a)

outer()

执行结果:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-9-7b758191e4f5> in <module>()
      9     print("Outer", a)
     10 
---> 11 outer()

<ipython-input-9-7b758191e4f5> in outer()
      6         print("Inner", a)
      7 
----> 8     inner()
      9     print("Outer", a)
     10 

<ipython-input-9-7b758191e4f5> in inner()
      3 
      4     def inner():
----> 5         a += 1
      6         print("Inner", a)
      7 

UnboundLocalError: local variable 'a' referenced before assignment

添加nolocal关键字

def outer():
    a = 1

    def inner():
        nonlocal a
        a += 1
        print("Inner", a)

    inner()
    print("Outer", a)

outer()

执行结果:

Inner 2
Outer 2

闭包

闭包也称词法闭包,如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure),这里说的作用域就是nonlocal。

通俗来讲,闭包就是把一个函数(方法)作为一个变量来使用。

在python中创建闭包必须满足的标准将在以下几点:

  • 必须有一个嵌套函数(函数内部的函数)。
  • 嵌套函数必须引用封闭函数中定义的值。
  • 闭包函数必须返回嵌套函数。

利用闭包实现一个计数器:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def counter():
    i = 0
    def nested():
        nonlocal i
        i += 1
        return i

    return nested

c = counter()
print(c(),c(),c(),end=" ")

返回的函数并没有立刻执行,而是直到调用了c()才执行。
返回的函数中不要引用循环变量:

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

print(f1()) 
print(f2()) 
print(f3())

执行结果:

9
9
9

全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。

如果一定要使用循环变量,解决方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

def count():
    def f(j):
        def g():
            return j*j
        return g
    
    fs = []
    for i in range(1, 4):
        fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
    return fs


f1, f2, f3 = count()

print(f1()) 
print(f2()) 
print(f3())

执行结果:

1
4
9

相关文章

利用python同步windows和linux文件

写python脚本的初衷,每次在windows编辑完文件后,想同步到linux上去,只能够登录服务器,...

爬虫基本原理

爬虫基本原理 一、爬虫是什么? 百度百科和维基百科对网络爬虫的定义:简单来说爬虫就是抓取目标网站内容的工具,一般是根据定义的行...

Django 函数和方法的区别

函数和方法的区别 1、函数要手动传self,方法不用传 2、如果是一个函数,用类名去调用,如果是一个方法...

Django 知识补漏单例模式

单例模式:(说白了就是)创建一个类的实例。在 Python 中,我们可以用多种方法来实现单例模式&#x...

Django基础知识MTV

Django简介 Django是使用Python编写的一个开源Web框架。可以用它来快速搭建一个高性能的网站。 Django也是一个MVC框架。但是在Dj...

Python mysql 索引原理与慢查询优化

一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。