实用解决Python作用域问题

article/2025/11/6 21:09:33

前言:一直以来对Python的作用域问题有很多的疑惑,看了很多大牛的讲解之后有所收获,所以就记录下来

1、块级作用域

想想此时运行下面的程序会有输出吗?执行会成功吗?

1

2

3

4

5

6

7

8

9

10

11

12

#块级作用域

 

if 1 == 1:

    name = "lzl"

 

print(name)

 

for i in range(10):

    age = i

 

print(age)

我们先看下执行结果

1

2

3

4

5

C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py

lzl

9

 

Process finished with exit code 0

代码执行成功,没有问题;在Java/C#中,执行上面的代码会提示name,age没有定义,而在Python中可以执行成功,这是因为在Python中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功;

2、局部作用域

回顾之前学过的知识,我们学函数的时候,函数是个单独的作用域,Python中没有块级作用域,但是有局部作用域;看看下面的代码

1

2

3

4

5

6

#局部作用域

 

def  func():

    name = "lzl"

 

print(name)

运行这段代码,想想会不会有输出?

1

2

3

4

Traceback (most recent call last):

  File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py", line 23, in <module>

    print(name)

NameError: name 'name' is not defined

运行报错,我相信这个大家都能理解,name变量只在func()函数内部中生效,所以在全局中是没法调用的;对上面代码做个简单调整,再看看结果如何?

1

2

3

4

5

6

7

#局部作用域

 

def  func():

    name = "lzl"

 

func()          #执行函数

print(name)

对之前的代码添加了一句代码,在变量name打印之前,执行了一下函数,此时打印会不会有变化?

1

2

3

4

Traceback (most recent call last):

  File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py", line 23, in <module>

    print(name)

NameError: name 'name' is not defined

执行依然报错,还是回到刚才那句话:即使执行了一下函数,name的作用域也只是在函数内部,外部依然无法进行调用;把前两个知识点记住,接下来要开始放大招了

3、作用域链  (这点很重要)

搜索变量名的优先级:局部作用域 > 嵌套作用域 > 全局作用域 > 内置作用域

对函数做下调整,看看下面的代码执行结果如何?

1

2

3

4

5

6

7

8

9

10

#作用域链

 

name = "lzl"

def f1():

    name = "Eric"

    def f2():

        name = "Snor"

        print(name)

    f2()

f1()

学过函数,肯定知道最后f1()执行完会输出Snor;我们先记住一个概念,Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错

4、终极版作用域

好,铺垫了够了,终极版的来了~~

1

2

3

4

5

6

7

8

9

10

11

12

#终极版作用域

 

name = "lzl"

 

def f1():

    print(name)

 

def f2():

    name = "eric"

    f1()

 

f2()

想想最后f2()执行结果是打印“lzl”呢,还是打印“eric”?记住自己的答案,现在先不把答案贴出来,先看看下面这段代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#终极版作用域

 

name = "lzl"

 

def f1():

    print(name)

 

def f2():

    name = "eric"

    return f1

 

ret = f2()

ret()

 

#输出:lzl

执行结果为“lzl”,分析下上面的代码,f2()执行结果为函数f1的内存地址,即ret=f1;执行ret()等同于执行f1(),执行f1()时与f2()没有任何关系,name=“lzl”与f1()在一个作用域链,函数内部没有变量是会向外找,所以此时变量name值为“lzl”;理解了这个,那么刚才没给出答案的那个终极代码你也知道答案了

1

2

3

4

5

6

7

8

9

10

11

12

13

14

#终极版作用域

 

name = "lzl"

 

def f1():

    print(name)

 

def f2():

    name = "eric"

    f1()

 

f2()

 

# 输出:lzl

是的,输出的是“lzl”,记住在函数未执行之前,作用域已经形成了,作用域链也生成了

    5、在函数中如何使用变量,谁会被修改,谁可以使用?

先看一个例子:

     上面的例子会报出错误,因为在执行程序时的预编译能够在test_scopt()中找到局部变量variable(对variable进行了赋值)。在局部作用域找到了变量名,所以不会升级到嵌套作用域去寻找。但是在使用print语句将变量variable打印时,局部变量variable并有没绑定到一个内存对象(没有定义和初始化,即没有赋值)。本质上还是Python调用变量时遵循的LEGB法则和Python解析器的编译原理,决定了这个错误的发生。所以,在调用一个变量之前,需要为该变量赋值(绑定一个内存对象)。
注意:为什么在这个例子中触发的错误是UnboundLocalError而不是NameError:name ‘variable’ is not defined。因为变量variable不在全局作用域。Python中的模块代码在执行之前,并不会经过预编译,但是模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道。Python虽然是一个静态作用域语言,但变量名查找是动态发生的,直到在程序运行时,才会发现作用域方面的问题

      这就涉及到了可变和不可变对象的问题:

  • 不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。
  • 可变对象,该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的出地址,通俗点说就是原地改变

      其中 string ,tuple和numbers是不可更改的对象,而list,dict,set则是可变的对象

      上面的程序中的 variable是一个 string对象,是一个不可变的,所以我们如果要修改的话,比如得到它的大写(upper方法),那么只能建立一个新的string接受它的返回值,而不能在原有的对象上修改。

      上述怎么做才可以不报错呢,把 variable=variable.upper() 改为 temp=variable.upper()  就可以了,让系统在预编译的时候找不到variable变量,也就没有上述错误发生了。

再看一个例子: 以 list 列表为例

      这就不会报错,因为list是可变对象,可以直接进行修改,所以我们就不用variable=variable.pop() 这样的copy操作啦,更何况pop方法之后返回pop的值,而不是原有list的copy,以后编程的时候注意这点。

      所以在函数中我们可以使用其外部的变量,但是最好注意可变和不可变对象的区别,以及对象方法的返回值。(编程注意)

 

参考博客:http://python.jobbole.com/86465/

                    https://www.cnblogs.com/fireporsche/p/7813961.html

                    https://www.cnblogs.com/sun-haiyu/p/7096918.html

                    https://blog.csdn.net/miantian180/article/details/79300062

 

 

 


http://chatgpt.dhexx.cn/article/8rKwIgq2.shtml

相关文章

python变量的作用域

作用域又可以被称为命名空间&#xff0c;指变量起作用的范围。Python变量作用域可以分为四种&#xff0c;分别为局部作用域、嵌套作用域、全局作用域、内置作用域。 作用域英文简写局部作用域LocalL嵌套作用域EnclosedE全局作用域GlobalG内置作用域Built-inB 四种作用域中变量…

linux-虚拟化管理工具

一、虚拟化管理工具 1.虚拟机的安装 用图形方式进行虚拟机的安装 安装镜像 设置虚拟机名字和占用内存大小 2.虚拟机的脚本安装 vim /bin/vm_create.sh 建立在/sbin目录底下&#xff0c;方便以后使用 #!/bin/bash ##幻数&#xff0c;脚本中命令…

常用虚拟机软件推荐

很多时候&#xff0c;由于工作的需要&#xff0c;都需要在不同的系统环境中进行调试开发&#xff0c;要么自己有多台电脑&#xff0c;安装不同的系统&#xff0c;要么给电脑装多系统。但这些都不是很现实&#xff0c;前者要资金&#xff0c;后者想进行系统切换也够费劲的了&…

理解全虚拟、半虚拟以及硬件辅助的虚拟化

接触过的一些搞了几年云计算的童鞋&#xff0c;也没明白常见的几种虚拟机技术方案的异同&#xff0c;比如只是记住了半虚拟要在虚拟机装驱动而全虚拟不需要&#xff0c;也不知道有时候为什么需要打开BIOS里的VT项。本人呢&#xff0c;在看了各种讲解虚拟化的书籍之后&#xff0…

虚拟化(二):虚拟化及vmware workstation产品使用

虚拟化&#xff08;一&#xff09;&#xff1a;虚拟化及vmware产品介绍 vmware workstation的最新版本是10.0.2。相信大家也都使用过&#xff0c;其中的简单的虚拟机的创建&#xff0c;删除等&#xff0c;都很简单&#xff0c;这里就不再详细说明了&#xff0c;下面我将简单介绍…

什么是虚拟化?

什么是虚拟化&#xff1f; “虚拟化“这个词只要是接触过计算机和网络的&#xff0c;或多或少都有听过。什么虚拟机、存储虚拟化、网络虚拟化、网络功能虚拟化&#xff08;NFV&#xff09;、虚拟资源池……今天从什么是虚拟化讲起。 什么是虚拟化 由于虚拟化在各种企业的技术…

虚拟化管理工具的安装与使用

虚拟化管理工具的安装与使用 Libvirt是一个软件的集合&#xff0c;包括API库&#xff0c;后台运行程序(Libvirtd)和命令行工具(virsh)。 Libvirt主要有下面3个功能&#xff1a; 1 虚拟机管理&#xff1a;以虚拟机为对象&#xff0c;Libvirt提供了定义&#xff0c;删除&#x…

开源虚拟化工具VirtualBox安装部署

什么是Virtualbox VirtualBox是一款由Oracle开发和维护的免费开源虚拟化软件&#xff0c;用于在一台计算机上创建和管理多个虚拟机。它允许用户在单个物理计算机上运行多个操作系统&#xff0c;例如Windows、Linux、macOS等。VirtualBox提供了一个虚拟化环境&#xff0c;使用户…

虚拟机的虚拟化如何开启?

大家可以在任务管理器-性能中&#xff0c;查看“虚拟化”是【已启用】还是【已禁用】。如果是禁用了&#xff0c;可以接着往下看我们如何开启虚拟化。 1、关闭电脑的快速启动 控制面板-电源选项-选择电源按钮的功能-更改当前不可用的设置&#xff1b;把关机设置中的【所有都取…

kvm虚拟化管理工具

kvm虚拟化管理工具 一、什么是云计算&#xff1f;二、云计算的基础KVM虚拟化三、安装kvm虚拟化管理工具四、virsh虚拟机的日常操作(开关&#xff0c;挂起虚拟机&#xff0c;导配置文件&#xff0c;磁盘增容&#xff0c;转化磁盘格式等&#xff09;五、快照管理六、KVM虚拟机的克…

有哪些虚拟化和容器化工具推荐? - 易智编译EaseEditing

以下是几个常用的虚拟化和容器化工具推荐&#xff1a; VMware vSphere&#xff1a; VMware vSphere 是一套完整的虚拟化平台&#xff0c;包括虚拟化服务器、虚拟化存储和虚拟化网络。 它提供了高性能的虚拟机管理和资源调度功能&#xff0c;适用于企业级的虚拟化部署。 Docke…

KVM虚拟化工具简介及安装

文章目录 1. KVM简介2. 安装前提3. KVM安装4. KVM启用5. 虚拟机安装和设置 1. KVM简介 Kernel-based Virtual Machine的简称&#xff0c;是一个开源的系统虚拟化模块&#xff0c;自Linux2.6.20之后集成在Linux的各个主要发行版本中。它使用Linux自身的调度器进行管理&#xff…

虚拟化工具介绍 (资源)

2019独角兽企业重金招聘Python工程师标准>>> 常见的虚拟化产品:docker、Hyper-V、VMware、VirtualBox、XenServer、Kvm、Qemu、OpenVZ、Xen、CloudStack、Openstack、云计算、云其他。 常见的虚拟化 技术 :ESXI、XEN、KVM、HP-V、Docker、Virtual-BOX, 使用最广泛…

AppScan 10中文版

教程&#xff1a; 1、下载解压缩&#xff0c;得到获得AppScan10中文版原程序&#xff1b; 2、首先双击“AppScan_Setup_10.0.0.exe”开始安装&#xff0c;选择简体中文&#xff1b; 3、勾选“我接受许可协议中的全部条款”&#xff0c;然后继续安装&#xff1b; 4、选择软件安…

安全测试工具APPScan下载安装及简单使用

一、安装 百度随便找了个网址下的&#xff0c;解压后如图&#xff1a;AppScan_Std_9.0.3.7_Eval_Win.exe是安装程序&#xff0c;LicenseProvider.dll是替换文件。安装包600多MB建议硬盘留存避免重复下载。 安装简单&#xff0c;注意修改下安装路径&#xff0c;另外会弹出提示是…

AppScan

AppScan是用于web项目的安全测试工具&#xff0c;扫描网站所有url&#xff08;自动手动&#xff09;&#xff0c;自动测试是否存在各种类型的漏洞。 使用步骤 选择记录 就会弹出appscan自带的浏览器&#xff0c;在其中输入账号密码&#xff0c;appscan就会自动记录 点击下一步…

Appscan测试工具简介

具用途&#xff1f; IBM公司的web扫描工具&#xff0c;对网站等WEB应用进行自动化的应用安全扫描和测试。 如何工作&#xff1f; 探索(Explore):在探索阶段&#xff0c;Appscan试图遍历网站中所有可用的链接&#xff0c;并建立一个层次结构。它发出请求&#xff0c;并根据响…

AppScan9.0

IBM近日发布了最新的Web 安全扫描器Appscan 9.0 &#xff0c;个人认为是目前商业扫描器中做的最好的&#xff0c;新的版本中增加了许多有用有的新特性&#xff0c;包括如下&#xff1a; .NET 服务器的 glass box 扫描 除了 Java 服务器之外&#xff0c;现在还可以在 .NET 服务…

appscan如何扫描移动应用APP

众所周知&#xff0c;appscan是一款企业级应用安全漏洞扫描神器&#xff0c;appscan怎么扫描移动应用&#xff08;也就是我们常说的APP&#xff09;。在此记录一下 Appscan扫描web应用时一般采用自动探索扫描和手动探索扫描两种方式&#xff0c;具体操作可以详见我CSDN另外一篇…

AppScan安装和扫描

AppScan安装步骤&#xff1a; **工作原理&#xff1a;**AppScan 是对网站等 Web 应用进行安全攻击来检查网站是否存在安全漏洞&#xff0c;根据起始页爬取要测的网站下的所有页面&#xff0c;随后利用SQL注入原理进行进行测试是否注入点以及跨站脚本攻击的可能&#xff0c;可能…