Python学习之变量的作用域

学习地址:http://www.jianshu.com/p/17a9d8584530

1、变量作用域LEGB

1.1变量的作用域

在Python程序中创建、改变、查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域。python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量能被访问的范围。即Python变量的作用域由变量所在源代码中的位置决定。

1.2高级语言对数据类型的使用过程

一般的高级语言在使用变量时,都会有下面4个过程。当然在不同的语言中也会有着区别。

  1. 声明变量:让编辑器知道有这一个变量的存在
  2. 定义变量:为不同数据类型的变量分配内存空间
  3. 初始化:赋值,填充分配好的内存空间
  4. 引用:通过引用对象(变量名)来调用内存对象(内存数据)

1.3作用域的产生

就作用域而言,Python与C有着很大的区别,在Python中并不是所有的语句块中都会产生作用域。只有当变量在Module(模块)、Class(类)、def(函数)中定义的时候,才会有作用域的概念。看下面的代码:

#!/usr/bin/env python
def func():
    variable = 100
    print variable
print variable

代码的输出为:

NameError: name ‘variable‘ is not defined

在作用域中定义的变量,一般只在作用域中有效。 需要注意的是:在if-elif-else、for-else、while、try-except\try-finally等关键字的语句块中并不会产成作用域。看下面的代码:

if True:
    variable = 100
    print (variable)
print ("******")
print (variable)

代码的输出为:

100
******
100

所以,可以看到,虽然是在if语句中定义的variable变量,但是在if语句外部仍然能够使用。

1.4作用域的类型:

在Python中,使用一个变量时并不严格要求需要预先声明它,但是在真正使用它之前,它必须被绑定到某个内存对象(被定义、赋值);这种变量名的绑定将在当前作用域中引入新的变量,同时屏蔽外层作用域中的同名变量。

L(local)局部作用域

局部变量:包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。

注意:如果需要在函数内部对全局变量赋值,需要在函数内部通过global语句声明该变量为全局变量。

E(enclosing)嵌套作用域

E也包含在def关键字中,E和L是相对的,E相对于更上层的函数而言也是L。与L的区别在于,对一个函数而言,L是定义在此函数内部的局部作用域,而E是定义在此函数的上一层父级函数的局部作用域。主要是为了实现Python的闭包,而增加的实现。

G(global)全局作用域

即在模块层次中定义的变量,每一个模块都是一个全局作用域。也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性。

注意:全局作用域的作用范围仅限于单个模块文件内

B(built-in)内置作用域

系统内固定模块里定义的变量,如预定义在builtin 模块内的变量。

1.5变量名解析LEGB法则

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

LEGB法则: 当在函数中使用未确定的变量名时,Python会按照优先级依次搜索4个作用域,以此来确定该变量名的意义。首先搜索局部作用域(L),之后是上一层嵌套结构中def或lambda函数的嵌套作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按这个查找原则,在第一处找到的地方停止。如果没有找到,则会出发NameError错误。

几个实例:

1.

def func():
    variable = 300
    print variable

variable = 100
func() #300
print variable  #100

2.

variable = 300

def test_scopt():

  print variable #variable是test_scopt()的局部变量,但是在打印时并没有绑定内存对象。

  variable = 200 #因为这里,所以variable就变为了局部变量

test_scopt()

print variable

上面的例子会报出错误,因为在执行程序时的预编译能够在test_scopt()中找到局部变量variable(对variable进行了赋值)。在局部作用域找到了变量名,所以不会升级到嵌套作用域去寻找。但是在使用print语句将变量variable打印时,局部变量variable并有没绑定到一个内存对象(没有定义和初始化,即没有赋值)。本质上还是Python调用变量时遵循的LEGB法则和Python解析器的编译原理,决定了这个错误的发生。所以,在调用一个变量之前,需要为该变量赋值(绑定一个内存对象)。

注意:为什么在这个例子中触发的错误是UnboundLocalError而不是NameError:name ‘variable’ is not defined。因为变量variable不在全局作用域。Python中的模块代码在执行之前,并不会经过预编译,但是模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道。Python虽然是一个静态作用域语言,但变量名查找是动态发生的,直到在程序运行时,才会发现作用域方面的问题



				
时间: 2024-11-05 06:22:19

Python学习之变量的作用域的相关文章

Python学习笔记 | 变量 + 引用 + 拷贝 + 作用域

在Python中,变量是没有类型的,在使用变量的时候,不需要提前声明,只需要给这个变量赋值即可.但是,当用变量的时候,必须要给这个变量赋值:如果只写一个变量,而没有赋值,那么Python认为这个变量没有定义(not defined). 一.变量和对象 1. 可变对象和不可变对象 在Python中,对象分为两种:可变对象和不可变对象,不可变对象包括int,float,long,str,tuple等,可变对象包括list,set,dict等.需要注意的是:这里说的不可变指的是值的不可变.对于不可变类

python学习7--变量的作用域

1.变量的作用域 (1)在函数内定义的变量包括实参,只在函数范围内起作用,局部变量类似之前. (2)全局变量,函数内部可调用函数外部,即使变量定义在函数后. 注:局部变量与全局变量定义与其它语言一样. 如若在函数内修改全局变量zjh,python会在函数内创建一个与全局变量名字一样 的局部变量代替.所以函数内对全局变量的修改不会影响全局变量. 注:如何使函数内部对全局变量修改起作用. 在函数内部用global关键字定义该全局变量. 例:使用前: 使用后:

Python学习笔记---变量与数据类型

Python中的变量与内置数据类型 本文只是我在慕课网学习<Python入门>这门课程时,摘录.整理的一些对自己比较重要的语法与提示.九成以上的内容以及所有代码示例,均摘抄自慕课网.由于我本人有一定C/C++语言基础,而本文主要供我自己复习使用,所以我偏向于摘录一些Python和C/C++之间的差异之处,可能造成本文语义上不一定连贯,建议有学习需求的读者直接前往慕课网学习该课程(链接:http://www.imooc.com/learn/177)或是查看该门课程授课教师廖雪峰先生官方网站所给出

php学习笔记-变量的作用域

这个东西很难理解,但很重要,我觉得非常容易出错. PHP中的变量按照作用域分为有两种,一种是global,一种是local. 函数内部声明的变量就叫local型变量,只能在函数内部被访问到.一句话,local型变量只能在函数内部定义以及引用. 函数外部声明的变量叫global型变量,只能在函数的外部访问到(除了GLOBALS).这种渣渣也能叫global,真是名不副实啊!我记得以前学习过的语言不是这个样子的,只要是global,函数外还是函数内都可以访问到的,但php就是这么难搞. 我们看一个l

5、python学习之变量

变量的定义:为了方便日后调用,存储程序中的一些中间结果变量定义的规则:1.要具有描述性2.变量名只能是字母.数字.下划线的任意组合,不可以是空格或特殊字符(!@#¥%*)3.不能以中文为变量名4.变量名的第一个字母不能是数字5.以下关键字不能声明为变量名['and','as','assert','break','class','continue','def','del','elif','else','except','finally','for','from','global','if','im

JavaScript系统学习小结——变量、作用域和内存问题

趁着写完小论文还未彻底消散的学习氛围,开始着重巩固自己JavaScript的基础知识,为秋招做最基本的准备. 变量:Js的变量可能保存两种不同数据类型的值:基本类型值和引用类型值. 基本类型包括:Undefined,Null,Boolean,Number和String,基本类型是按值访问方式: 引用类型的值是对象,是按引用方式引用: 在复制变量值时,两种数据类型的差异表现在: 复制基本类型值后,创建的是这个值的副本,彼此两个变量可以参与任何操作而不会互相影响: 复制引用类型值后,两个变量实际上将

Python 函数内变量的作用域

参考文献: Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域. 全局作用域(global):即在模块层次中定义的变量,每一个模块都是一个全局作用域.也就是说,在模块文件顶层声明的变量具有全局作用域,从外部开来,模块的全局变量就是一个模块对象的属性. 全局变量可以在函数内部访问,不能修改,修改想要修改可以用globa来装饰变量 注意:全局作用域的作用范围仅限于单个模块文件内. >>> x = 1 #定义一个变量 >&g

Python学习(2)变量、常量、注释

1.变量 变量的概念 :变量 是 为了存储 程序运算过程中的一些中间 结果,为了方便日后调用 变量的命名规则: 1. 要具有描述性 2. 变量名只能_,数字,字母组成,不可以是空格或特殊字符(#?<.,¥$*!~) 3. 不能以中文为变量名 4. 不能以数字开头 5. 保留字符是不能被使用 x=1 y=2 z=x*y print("x乘y等于:",z) 输出结果: x乘y等于: 2   2.常量 常量的概念:不变的量 pie = 3.141592653.... 在Python里面

python学习-day16:函数作用域、匿名函数、函数式编程、map、filter、reduce函数、内置函数r

一.作用域 作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变 二.匿名函数 lambda:正常和其他函数进行配合使用.正常无需把匿名函数赋值给一个变量. f=lambda x:x*x print(f) #打印指向该函数的内存地址 print(f(5)) #内存地址(5) 调用运行该函数 def cala(x): y=x*x return y z=cala(5) print(z) >>> <function <lambda> at 0x10137d950&g