Python入门(三十)命名空间和作用域

本文讲述了Python中函数和方法的组织结构,重点介绍了变量的作用域(全局变量和局部变量)、命名空间的层次结构,以及如何在函数内外访问和修改变量。还讨论了Python中全局和局部变量的区别以及使用`global`关键字的情况。
摘要由CSDN通过智能技术生成

函数(包括方法)是Python代码的主要组织形式,那你有没有发现,在函数中实际是可以引用函数外的变量的,但是在函数外面不能引用函数里的变量。

a = 10

def foo():
    b = a ** 2  #函数内部可以引用外部的变量
    print(f"{a=}, {b=}")

foo() #a=10, b=100
print(b) #NameError: name 'b' is not defined 但是外部不能使用函数内的变量

这种限制我们称呼变量的作用域限制。

每个变量只有一定范围内有效,这个范围我们称之为作用域。

上面的例子中,变量a是全局变量,它的作用域是全局的,程序中的任意地方都可以访问它,但是在函数内部定义的变量b,它是局部变量,它的作用域是函数内部,只在函数内部可以访问它。

所谓作用域就是指变量名/对象名在多大范围内是可见的/有效的,一个变量名既不能作用域太大,这样会引发广泛的命名冲突,也不能太小,这样很难实现变量的共享,所以一般都有多层次的作用域。一个层次的作用域,在Python里称为命名空间。

命名空间

Python的命名空间有三个层次(作用域):

  • 内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等,他们可以在任何地方进行直接的访问,不需要import。
  • 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量,如果要扩模块访问,需要import导入,遵循模块使用的规则。
  • 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

在使用变量的过程中,命名空间的查找顺序是:

局部的命名空间 -> 全局命名空间 -> 内置命名空间

也就是说,如果我们发现一个变量,首先看它是不是一个局部变量(在函数内部有被赋值),如果不是局部变量,看是否是一个全局变量(在函数外是否有被赋值),如果不是全局变量,可能是Python内置的变量,如果也不是内置变量,那这个变量就是未定义的。

反向来看,如果出现了重名,全局变量的名字将覆盖Python的内置变量,局部变量将覆盖全局变量。

比如下面的例子:

a = 10

def foo():
    a = 20
    print(f"在函数foo()内 {a=}")

foo()
print(f"在函数foo()执行后 {a=}")

首先定义了全局变量a,在函数里给a进行了赋值,在调用函数后,打印a的值,仍然是在全局变量时赋的值,全局变量的值并没有变化。

在函数外的

a = 10

实际是定义了一个为10的变量a

同样,在函数里

a = 20

是定义了一个为20 的变量a,这里的a是局部变量,而前面那个a是全局变量,当我们在函数里访问a时,访问的是定义的局部变量a。

那有没可能我在定义局部变量之前先访问全局变量呢?

def foo():
    print(f"在函数foo()内,刚开始访问", a)
    a = 20
    print(f"在函数foo()内 {a=}")

foo()
print(f"在函数foo()执行后 {a=}")

#UnboundLocalError: cannot access local variable 'a' where it is not associated with a value

实际上是不行,解释器分析发现这两个地方有冲突,直接给出了UnboundLocalError的异常。

作用域

作用域就是一个 Python 程序可以直接访问命名空间的变量、函数区域。

命名空间是从变量的角度来看的,就是这个变量在那个空间能被看到,作用域是从程序访问的角度来看的,就是在这个层级函数或方法可以访问到哪些变量。

作用域分层四个域:

  • L(Local):最内层,包含局部变量,比如一个函数/方法内部。
  • E(Enclosing):闭包,这个后面会学习。
  • G(Global):当前程序的最外层,比如当前模块的全局变量。
  • B(Built-in): 包含了内建的变量/关键字等,最后被搜索。

作用域的搜索层级是L –> E –> G –> B

在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

g_count = 0  # 全局作用域

def foo():
    l_count = 1  # 局部作用局

内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。在Python3.0中,可以使用以下的代码来查看到底预定义了哪些变量:

import builtins
print(dir(builtins))

几乎所有的内置函数、内置异常都在这里面。

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:

if True:
    msg = '作用域变量'

print(msg) #作用域变量

这与C++、Java语言等有很大的不同。

全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:

total = 0 # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
    #返回2个参数的和."
    total = arg1 + arg2 # total在这里是局部变量.
    print ("函数内是局部变量 : ", total)
    return total
 
#调用sum函数
sum( 10, 20 )
print ("函数外是全局变量 : ", total)

#函数内是局部变量 :  30
#函数外是全局变量 :  0

global 关键字

当内部作用域想修改外部作用域的变量时,就要用到 global 关键字了。

global声明变量是全局变量,例如:

num = 1
def fun1():
    global num  # 需要使用 global 关键字声明
    print(num) 
    num = 123
    print(num)


fun1()
print(num)

’’’
1
123
123
‘’‘

以上就是“Python入门(三十)命名空间和作用域”的全部内容,希望对你有所帮助。

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

在这里插入图片描述

二、Python必备开发工具

img

三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

五、Python练习题

检查学习结果。

img

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

img

最后祝大家天天进步!!

上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值