Python3萌新入门笔记(20)

这一篇教程,我们先来看一段代码。

示例代码:

x = 0  # 全局变量

def outside():  # 定义函数
    x = 1  # 局部变量,内嵌函数的外部变量

    def inside():  # 定义内嵌函数
        x = 2  # 局部变量
        return x

    return x, inside # 将变量值和函数返回

o, i = outside()  # 通过两个变量接收outside函数的返回值x和inside
print(x)  # 显示输出结果为:0
print(o)  # 显示输出结果为:1
print(i())  # 显示输出结果为:2

刚才的这段代码,可能不太容易理解。

因为里面包含了几部分我们没有接触过的内容。

第一部分,我们先来了解一下函数嵌套。

在Python中可以在函数的内部再定义函数。

大家能够看到,在上方代码中函数outside的内部,又定义了一个函数inside。

这种结构就是函数嵌套。

另外,在上方代码中,大家能够看到函数的返回值不仅可以返回多个,而且可以返回内嵌函数(这是闭包,后面会讲到)。

返回内嵌函数时,如果函数名称后方没有加上“()”,调用外层函数时不会立即执行返回的函数,需要在调用外层函数后,添加“()”来执行。例如,上方代码最后一句中的“i()”,就是执行变量中保存的函数。

而且,我们也可以用下面这种方法去执行返回的函数。

示例代码:(接上一段代码)

outside()[1]() # 调用外层函数时,获取的返回值列表中第2项是函数,加上()则会被执行。

这是外层函数有多个返回值时的方法,通过对外层函数返回值列表进行索引,找到函数执行。

如果,外层函数只有一个返回值,我们可以通过函数名称后方直接加上“()()”去执行返回的函数。

另外,在外层函数返回内嵌函数时,在函数名称后方加上了“()”,会在调用外层函数时自动执行。

大家可以通过运行以下代码进行对比。

示例代码:(返回函数不带括号)

def outside():
    print('执行外层函数!')

    def inside():
        print('执行内嵌函数!')

    return inside

outside()

示例代码:(返回函数带有括号)

def outside():
    print('执行外层函数!')

    def inside():
        print('执行内嵌函数!')

    return inside()

outside()

第二部分,我们来了解变量的作用域。

在上方代码中,我们能够看到有3个变量的名称都是x。

这3个x并非同一个变量,只是名称一样,它们的特点可以这么理解:

  • 最外层的变量x是全局变量
  • 函数outside中和inside定义的变量x,都是局部变量。
  • 函数outside中的变量x,相对于内嵌的函数inside,它是外部变量。

这3个变量有着不同的作用域。

如上图所示,3个x变量的作用域如下:

  • 最外层的变量x,它的作用域是整个模块中。
  • 函数outside中的变量x,作用域是函数outside内部以及内嵌函数inside。
  • 函数inside中的变量x,作用域是函数inside内部。

也就是说,全局变量作用域是当前模块内,而局部变量作用域是函数以及内嵌函数中。

但是,这里大家可能会有疑问,既然全局变量作用域是全局的,那么在函数中又创建同名变量不是冲突了吗?

这个不用担心,当在函数中创建与全局变量同名的局部变量时,在函数内部会自动屏蔽同名的全局变量。

所以,在本文开头的代码中,显示输出的结果并不相同。

下图就是3个变量x的值输出显示时的过程。

到这里,我们有必要来了解一下作用域的概念。

作用域也叫命名空间,命名空间是一个我们看不到的字典,字典的键记录变量的名称,字典的值记录着变量的值。

每个模块都会创建一个全局命名空间,用于记录模块的变量,包括全局变量和局部变量,以及其它导入模块中的变量。

每个函数调用时都会创建一个局部命名空间,用于记录函数的变量,包括函数的参数和函数内部创建的变量。

另外,还有内置命名空间,任何模块都能够访问,记录了内置函数和异常。

第三部分,我们来了解如何在函数中读取与修改全局变量。

首先,我们先来看读取全局变量。

一般情况下,我们在函数中可以直接读取全局变量。

这里我们看一段根据半径计算圆形周长的代码。

示例代码:

radius = 21  # 创建半径的变量并赋值

def get_perimeter():  # 定义获取周长的函数
    perimeter = round(2 * 3.14 * radius,2)  # 创建周长的变量保存计算结果
    return perimeter  # 返回结果

print(get_perimeter()) # 显示输出结果为:131.88

在上方代码中,我们定义了全局变量radius,在函数中我们可以直接调用这个变量参与计算。

但是,如果我们在函数中创建的局部变量如果与全局变量同名,这时候怎么调用全局变量呢?

我们可以借用内置函数globals来获取到全局变量。

示例代码:

def global_case():  # 定义函数
    x = 5  # 创建同名局部变量
    result = x * globals()['x']  # 通过globals函数获取全局变量x与局部变量x相乘
    return result  # 返回结果

print(global_case())  # 显示输出结果为:15

接下来,我们来看如何在函数中修改全局变量(或者叫重新绑定全局变量为其他值)。

当我们创建了某个全局变量,在函数中无法直接修改这个变量。

就像之前的代码中,即便在函数中给x赋值(例如x=1),也只是创建了一个新的局部变量,而不是对全局变量x进行修改。

那么,如何在函数中修改全局变量呢?

我们可以使用global关键字,声明要重新绑定的全局变量。

这样,Python解释器就能够知道,我们是要对已有的全局变量进行修改,而不是创建一个新的同名局部变量。

示例代码:

x = 10 # 创建全局变量

def change_global():  # 定义函数
    global x  # 声明要修改的全局变量
    x = 5  # 修改变量值

change_global()  # 调用函数
print(x)  # 显示输出全局变量x的值,结果为:5

在上方代码中,大家能够看到,我们定义了全局变量x和修改这个全局变量的函数change_global。

在修改全局变量的函数change_global中我们并没有设定返回值,它只起到修改的作用。

所以,当我们执行了这个函数,再显示输出变量x的值,就是经过修改后的值。

补充说明:如果想在内嵌函数中修改外层函数中的局部变量,可以使用关键字nonlocal进行声明。使用方法和关键字global类型。

示例代码:

def nonlocal_case():
    x = 10 # 创建局部变量

    def change_nonlocal():  # 定义函数
        nonlocal x  # 声明要修改的外部变量
        x = 5  # 修改变量值

    change_nonlocal() # 调用修改函数执行修改
    return x # 返回变量x的值

print(nonlocal_case())  # 显示输出全局变量x的值,结果为:5

第四部分,我们来了解一下闭包(closure)的概念。

在网上查了闭包的解释,百度百科中是这样说的:闭包由要执行的代码块(内嵌函数)和为自由变量(外部变量)提供绑定的计算环境(作用域/命名空间)组成。

注意,上面这段话中,括号里面的内容是我按照自己的理解添加的。

以我个人的观点,闭包就是由返回的内嵌函数和这个内嵌函数中用到的外部变量(1)以及其他函数(2)打包而成的一个整体。

(1)外部变量,包括:外层函数的参数变量以及外层函数中定义的局部变量

(2)其它函数,包括:外层函数中定义的其他内嵌函数

例如,在本文第一段代码中就有闭包的出现。

为了更清楚的解释闭包的概念,我们来看一段代码。

用户输入合成的宝石数量,然后执行合成计算。

示例代码:

def synthesis():
    count = int(input('请放入宝石:'))
    while True:
        if count < 3:
            count += int(input('宝石太少,请再放入一些宝石:'))
        else:
            break

    def execute():
        result = count // 3  # 调用外部变量进行整除运算
        print('您放入了%s颗宝石,合成了%s颗高级宝石!' % (count,result))

    return execute 

exe = synthesis() # 调用函数
print('------------------开始合成------------------')
exe() #执行闭包内容

这段代码中,闭包包含的内容,如下图所示。

如图所示,外层函数被调用,执行return语句时,会将内嵌函数返回,形成闭包存入变量exe。

exe中的闭包内容包括:外层函数中变量count和内嵌函数excute。

exe()语句会执行闭包中的内容,我们可以认为执行了以下语句。

count = *  # "*"表示外层函数执行后,变量count的最终值
def execute():
    result = count // 3  # 调用外部变量进行整除运算
    print('您的%s颗宝石,合成了%s颗高级宝石!' % (count, result))

本节知识点:

1、嵌套函数;

2、作用域的概念;

3、函数中对外部变量与全局变量的修改;

4、闭包的概念。

本节英文单词与中文释义:

1、inside:内部

2、outside:外部

3、radius:半径

4、perimeter:周长

5、case:情形

6、synthesis:合成

7、execute:执行

练习:独立完成宝石合成的示例代码。

转载自:魔力 • Python » Python3萌新入门笔记(20)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值