前面已经了解了变量的一些知识。变量有一个名称,通过变量的名称可以在计算机的存储空间中存取数据。这节课主要了解Python的标识符、变量和嵌套函数的作用域。
标识符
标识符用于Python语言的变量、函数、类等数据的命名。标识符的命名需要遵循下面的规则。
① 可以由字母(大写A—Z或小写a—z)、数字(0—9)和_(下划线)组合而成,但不能由数字开头;
② 不能包含除_以外的任何特殊字符,如:%、#、&、逗号、空格等;
③ 不能包含空白字符(换行符、空格和制表符称为空白字符);
④ 标识符不能是Python语言的关键字和保留字;
⑤ 标识符区分大小写,num1和Num1是两个不同的标识符。
⑥ 标识符的命名要有意义,做到见名知意。
Python的变量名称、函数名称、类的名称(包括自定义类的名称)都属于标识符。
变量的作用域
变量作用域是指我们在程序中命名的变量在多大范围能够访问到它。在函数内部声明的变量,在函数外部是否能够访问?在模块中声明的变量,在函数内部是否能够访问?这些都是变量作用域要解决的问题。下面是一段有关变量作用域范围的代码。
#定义π变量
π = 3.14
#定义求圆面积函数
def area(r):
s = r * r * π;
print(s)
area(10)
print(s)
上面的代码是求圆的面积。在模块头部声明了变量π,变量π被定义的area函数在内部使用,area函数求出圆的面积并输出结果。print语句在这段代码中使用了两次:第一次是在area函数内部使用,输入参数是在area函数内部声明的变量s;第二次是在模块中使用,输入参数是在area函数内部声明的变量s。
在执行程序的过程中,程序输出如下信息:
314.0
Traceback (most recent call last):
File "D:/pythoncode/test.py", line 8, in <module>
print(s)
NameError: name 's' is not defined
从程序的输出结果可以看出。第一条print语句被正确执行,输出了圆的面积。第二条print语句在执行过程中报错,错误信息是“NameError: name 's' is not defined”,大体意思是“名称错误:名称‘s’没有被定义”。从给出的错误信息可以得出下面的结论:
在函数内部声明的变量不能在函数外部访问,函数内部声明的变量为局部变量,其作用域仅限于函数内部。
有局部变量就有全局变量,上面代码中的π就是全局变量。这里的全局变量是指在模块范围内的全局变量,其作用域是整个模块。全局变量可以在模块内的函数内部使用,但需要遵循先声明后使用的原则。
使用global关键字可以提升函数内部的局部变量为全局变量,当使用global关键字修饰变量时,该变量被提升为全局变量。
#定义π变量
π = 3.14
#定义求圆面积函数
def area(r):
global s
s = r * r * π;
print(s)
area(10)
print(s)
在上面的代码中。函数area内部声明的s使用了global关键字,局部变量s被提升为全局变量,因此在函数的外部也可以使用变量s。
在执行程序的过程中,程序输出如下信息:
314.0 314.0
从程序的输出结果可以看出。代码中的第二条print语句被正确执行,输出了圆的面积,其输入的参数就是在area函数内部声明的变量s。
在上面的探讨中,我们了解了局部变量和全局变量的作用域,也知道了使用global关键字可以把函数内部的局部变量提升为全局变量。不过还有个问题没有弄明白,当全局变量的名称和函数体内局部变量的名称相同时,哪个变量会被使用呢?
#定义π变量
π = 3.14
#定义求圆面积函数
def area(r):
π = 3.14159
s = r * r * π;
print(s)
area(10)
上面的代码在area函数内部又声明了一个变量π,这个变量π是局部变量,其精度要比全局变量π高。那么问题来了,在程序执行过程中,计算圆的面积是用局部变量的π?还是用全局变量的π呢?
在执行程序的过程中,程序输出如下信息:
314.159
程序的执行结果给出了答案,当模块内全局变量的名称和函数体内局部变量的名称相同时,在函数体内声明的局部变量将覆盖与其名称相同的全局变量。
嵌套函数的作用域
Python语言是支持函数嵌套的,即在函数体内部可以嵌套定义子函数。那么嵌套的子函数是否可以在函数外部调用呢?它的作用域又是什么范围呢?
#定义嵌套函数
def foo():
m = 3
def bar():
n = 4
print(m+n)
bar()
#调用foo函数
foo()
#调用foo函数内部的bar函数
bar()
上面的代码定义了foo函数,在foo函数内部又嵌套定义了bar子函数。bar子函数使用了foo函数声明的局部变量m,并输出m与n的和。foo函数的最后一条语句调用了bar函数。需要记住,函数必须被调用后才执行函数体内代码。
在执行程序的过程中,程序输出如下信息:
7
Traceback (most recent call last):
File "D:/pythoncode/test.py", line 11, in <module>
bar()
NameError: name 'bar' is not defined
从程序执行结果可以看出。foo函数被正确执行,并输出了正确的结果数字7。因此在嵌套函数中,子函数内部可以访问在父函数声明的变量。对子函数来说,父函数声明的变量在整个函数体内就是全局变量。代码中的最后一条语句是调用foo函数内部嵌套的子函数bar,在执行到这条语句时程序报错,显然在函数体内嵌套的函数是不能被外部调用的,其作用域仅限于函数体内部。