Python函数中的作用域规则详解
作者:一只懐坏旭 发布时间:2023-02-14 04:32:28
Python是静态作用域语言,但是它自身是一个动态语言。在Python中变量的作用域是由变量在代码中的位置决定的,与C语言有些相似,但不是完全一样。
在Python 2.0及之前的版本中,Python只支持3种作用域,即局部作用域,全局作用域,内置作用域;在Python
2.2中,Python正式引入了一种新的作用域 — 嵌套作用域;嵌套作用域的引入,本质上为Python实现了对闭包的支持。
1、简单介绍一下闭包
def test():
A = 3
B = 4
def stu():
C = 3
return A+B+C
return stu
stu = test()
stu
在上述此代码中stu方法定义在test的内部,内部函数stu即可以使用外部函数test的变量,我们称这种行为叫做闭包。
2、在Python中,并不是任何代码块都能引入新的作用域
Python中不是任何代码块都可以引入新的作用域这与C有很大的不同:
在C中:
#include<stdio.h>
int main() {
if(2 > 0) {
int i = 0;
}
printf("i = %d", i);
return 0;
}
在上述代码中,if子句引入了一个局部作用域,变量i就存在于这个局部作用域中,但对外不可见,因此,接下来在printf函数中对变量i的引用会引发编译错误。
但是,在Python中却并非如此:
if True:
i = 0
print i
在上述代码中,if子句并没有引入一个局部作用域,变量i仍然处在全局作用域中,因此,变量i对于接下来的print语句是可见的。
实际上,在Python中,只有模块,类以及函数才会引入新的作用域,其它的代码块是不会引入新的作用域的。
在Python中,使用一个变量之前不必预先声明它,但是在真正使用它之前,它必须已经绑定到某个对象;而名字绑定将在当前作用域中引入新的变量,同时屏蔽外层作用域中的同名变量,不论这个名字绑定发生在当前作用域中的哪个位置。
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
NameError: name 'i' is not defined
>>>
运行结果报错:
NameError: name ‘i’ is not defined
程序运行时,Python首先在函数f的本地作用域中查找变量i,查找失败,接着在全局作用域和内置作用域中查找变量i,仍然失败,最终抛出NameError异常。
>>> def f():
... i = 8
... print(i)
...
>>> f()
8
>>> print(i)
0
>>>
运行结果显示:
8和0
i = 8是一个名字绑定操作,它在函数f的局部作用域中引入了新的变量i,屏蔽了全局变量i,因此f内部的print语句看到的是局部变量i,f外部的print语句看到的是全局变量i。
>>> i = 0
>>> def f():
... print(i)
... i = 0
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
UnboundLocalError: local variable 'i' referenced before assignment
>>>
运行结果报错:
UnboundLocalError: local variable ‘i’ referenced before assignment
在上述中,函数f中的变量i是局部变量,但是在print语句使用它的时候,它还未被绑定到任何对象之上,所以抛出异常。
3、在Python中,名字绑定在所属作用域中引入新的变量,同时绑定到一个对象。
名字绑定发生在以下几种情况之下:
参数声明:参数声明在函数的局部作用域中引入新的变量;
赋值操作:对一个变量进行初次赋值会在当前作用域中引入新的变量,后续赋值操作则会重新绑定该变量;
类和函数定义:类和函数定义将类名和函数名作为变量引入当前作用域,类体和函数体将形成另外一个作用域;
import语句:import语句在当前作用域中引入新的变量,一般是在全局作用域;
for语句:for语句在当前作用域中引入新的变量(循环变量);
except语句:except语句在当前作用域中引入新的变量(异常对象);
来源:https://blog.csdn.net/qq_45691220/article/details/123354446


猜你喜欢
- ASP由于是一种古老的语言,它的一些功能对UTF-8支持非常差。比如,你想生成一个UTF-8格式的文件,使用常用的 scrīpting.Fi
- 对于时间的选择问题,查到的大部分为两种情况:1.存在readonly属性的2.没有readonly属性的可直接赋值send_keys()测试
- 方法一一般情况下,SQL数据库的收缩并不能很大程度上减小数据库大小,其主要作用是收缩日志大小,应当定期进行此操作以免数据库日志过大1、设置数
- 目录1、父传值给子组件2、子传值给父组件3、子调用父组件中的方法4、父调用子组件中的方法1、父传值给子组件父组件:<template&
- 直接在table标签中设置下不就行了吗?这是静态的,如果要动态设置你会吗?function com_onresize(){var conte
- mac下安装mysql8.0.11时 要求输入密码 之后想修改密码注意 此方法适用于mac下的mysql8.0.11 其他版本不一定相同1.
- 利用zipfile模块和pandas获取数据,代码比较简单,做个记录吧:# -*- coding: utf-8 -*-""
- 目录楔子faker使用方法基本使用地理信息类基础信息类计算机基础、Internet信息类网络基础信息类浏览器信息类数字类文本、加密类时间信息
- 本文实例讲述了python实现string和dict的相互转换方法。分享给大家供大家参考,具体如下:字典(dict)转为字符串(string
- 1.前言数据库的重要性相信大家都有所了解,作为各种数据的电子资料夹,其中可能包含了各种信息,从企业员工信息到网站访问或成交数据无所不包,甚至
- declare @id  
- 1、有一个论坛,帖子的数据巨大,请简要说明如何提高用户搜索帖子的效率。 在程序方面,可以使用页面缓存技术。在前台界面着设计方面也可以让用户输
- 微信(WeChat) 是腾讯公司于2011年1月21日推出的一个为智能终端提供即时通讯服务的免费应用程序,由张小龙所带领的腾讯广州研发中心产
- 此次遇到的问题是在import pycurl 时报错pycurl:libcurl link-time version is older th
- 这几天研究UTF-8编码,太晕了,把我的看法和各位讨论讨论。欢迎来批啊。以下都是我的想法,哪里有不对的请不吝赐教,帮忙指出来。相关的题外话:
- 计时器用来定时执行任务,分享一段代码:package mainimport "time"import "fmt
- 如果你的模型中含有 datetime 类型的字段,表单中需要用户输入日期和时间,那么你如何保证不同用户输入的时间都遵循一定的格式 (DD/M
- 在一些朋友安装完SQL Server 2008之后大多会遇到连接出错的问题。特别对于我们这样的新手而言简直郁闷的要死,好不容易装玩了又出现了
- 刚开始使用django,在创建第一个app时被提示不知道命令runserver,百度得出是环境变量的问题。1、配置python变量环境,C:
- windows版本下需要先安装ffmpeg工具:1:先下载指定(https://ffmpeg.zeranoe.com/builds/) 有S