编程语言从早至今,可以分为面向过程编程、面向函数编程和面向对象编程。BASIC语言是典型的面向过程编程的语言,C语言支持面向函数编程,但不支持面向对象,JAVA只支持面向对象编程,python同时支持面向函数和面向对象编程。对于大型程序,无疑,面向对象编程更好一些。由于存在各种封装等级、封装方法,变量在不同的位置具有不同的有效区域。
一、全局变量与局部变量
那这些和全局变量、局部变量有什么关系?在面向对象编程中,所有的对象,包括变量、方法、属性等等都被封装在类或函数中,程序看起来是这样的:
PI = 3.1415926
class c1():
pass
class c2():
pass
......
def f1():
a = 10
pass
def f2():
pass
......
def main():
pass
mian()
当然,上面只是个例子,实际并非一定如此。但也能基本说明问题了。绝大多数变量都被封装在自己的函数或类里,属于局部变量,只能在自己的小天地里画圈圈。
这样做的好处是,作用域限定,互不干扰,各司其职。那些大家共同需要,共同维护的数据一般才声明为全局变量,它在所有作用域都可读。在Python里,它一般是全字母大写,并在顶头位置。我们非常不建议在包装精美的程序框架里,突然冒出个“孤魂野鬼”似的随意定义的全局变量。因此,在使用全局变量,我们通常有以下建议:
1.无论在何处对全局变量进行重新赋值,请使用global关键字
2.对于列表,字典等特殊数据类型的全局变量,可以在函数体内修改其元素,例如list.append()
3.不要在函数、类中创建全局变量。这样会让全局变量不可查,不可控。
二、python的作用域
在python中,作用域指的是某个变量的有效范围。
1. python中没有块级作用域
python中的块,指的是类似for循环、while循环、if条件语句,with语句等一个块块代码。没有块级作用域就是说在这些语句内部的变量和在外面的变量是一样的。这点与java和c#语言是有区别的。
if 1==1: #if,for 等构成一个代码块 name = 'zhang' #代码块结束 print(name)
上面的代码在python中正常执行。但在JAVA中报错,java的解释器会认为变量name没有预先定义。
2. python中的最小作用域是函数,函数管理者最小有效范围的局部变量。
这一点相信没有人会有疑问
3.python采用作用域链的机制,类似类的继承机制。
当在函数内使用一个它本身内部不存在的变量时,它会逐级向外围更大的作用域进行查找,如果最后还没找到则报错。
name = 'zhang' def func(): name='a' #print(name) def f2(): name='b' print(name) f2() func() >>> b
变量name在func和f2中都有定义,执行func()的时候,先赋值name='a',然后执行f2(),重新定义name = 'b',在执行print(name)的时候,输出的结果为‘b’
4. python内的函数在未执行之前,作用域和作用域链就已经全部确定。
name ='alex' def f1(): print(name) #f1继承自己的作用域 def f2(): name = 'eric' f1() f2() #执行f1() >>> alex
下面的例子也一样:
name = 'zhang' def f1(): print(name) def f2(): name = 'eric' #print(name) return f1 ret = f2() ret() >>> zhang
4. python是门动态语言,函数在未执行之前,只是简单的扔到内存里。
name = 'zhang' def f2(): name = 'eric' print(age) return f1 def f1(): print(name) age = 18 ret = f2() ret()
上面代码中,f1函数和age变量都出现在f2函数之后,执行程序没有任何问题。