python变量总结: 全局变量、局部变量、类变量、实例变量以及global和nonlocal关键字的使用示例

前言:Python也同多数编程语言一样,也有全局变量与局部变量的概念, 但是与其他编程语言又有所不同:
全局变量与局部变量两者的本质区别就是在于作用域——
用通俗的话来理解的话,全局变量是在整个py文件中声明,全局范围内都可以访问
局部变量是在某个函数中声明的,只能在该函数中调用它,如果试图在超出范围的地方调用,程序就爆掉了
如果在函数内部定义与某个全局变量一样名称的局部变量,就可能会导致意外的效果,可能不是你期望的。因此不建议这样使用,这样会使得程序很不健全。

一、python变量一般有以下四种类型:

  1、全局变量:在模块内、在所有函数外面、在class外面,这就是全局变量。
  2、局部变量:在函数内、在class的方法内(未加self修饰的) ,这就是局部变量
  3、静态变量:在class内的,但不在class的方法内的,这就是静态变量
  4、实例变量:在class的方法内的,用self修饰的变量,这就是实例变量
二、简要分别介绍

1、全局变量和局部变量:

# coding:utf-8
ahead = 'HelloWorld'  # 全局变量
showList = []  # 全局变量

def printAhead():
    print ahead

def printOther():
    city = 'beijing'  # city是局部变量
    print city + ahead

def printList():
    global showList  # global代表引用全局变量,没办法,不写的话,showList就成局部变量了
    showList.append(1)
    showList.append(2)
    print showList

printAhead()
printOther()
printList()

'''
输出结果为:

HelloWorld
beijingHelloWorld
[1, 2]
'''


2、静态变量和实例变量

class Person(object):
    TAG = "Person"  # 静态变量

    def __init__(self, name):   # self 当前的实例对象(简单的说一下,其实都是引用哈)
        print "__init__", Person.TAG  # 这里调用了静态变量
        self.personName = name  # personName是实例变量 (简单说就是因为self,哈哈)

    def printname(self):
        group = "BeiJing_"   # group是局部变量
        print group + self.personName  # self.personName, 调用实例变量

if __name__ == "__main__":
    p = Person("YaoMing")
    p.printname()
    print "__main__", p.TAG

'''
输出结果为:

__init__ Person
BeiJing_YaoMing
__main__ Person
'''


三、情形举例:

1、Global全局变量的使用

global a
def a_fun():
    a = 2
    a += 1
    print a
    # 注意这里没有使用return a
def do():
 	a_fun()
 	# 并把a方法的value(a)进行运算
 	a+=1   
    # 我们写一个main函数来调用这个do的过程
if __name__ == '__main__':
 	do()
 	print a
#报错如下:
'''
Traceback (most recent call last):
  File "/Users/a6/Downloads/PycharmProjects/AB/test_global.py", line 18, in <module>
    do()
  File "/Users/a6/Downloads/PycharmProjects/AB/test_global.py", line 15, in do
    a+=1
UnboundLocalError: local variable 'a' referenced before assignment
'''

原因:程序出现调试错误:local variable 'a' referenced before assignment,由此,我们可以看出局部变量在方法中是不能传递的。为了能够使用几个方法返回的值,并在do()这个函数中进行运算,我们引入了全局变量global a,现在我们对以上的程序做出进行以下调整:

#-*- coding:utf-8 -*-
global a
def a_fun():
    global a   # A块
    a = 2
    a += 1
    print "a_fun: ", a
    # 注意这里没有使用return a
def do():
    global a  # B块
    a_fun()
    a+=1   
if __name__ == '__main__':
 	do()
 	print "__main__", a

'''
注释A块,会报如下错误:
a+=1   #UnboundLocalError: local variable 'a' referenced before assignment
NameError: global name 'a' is not defined


注释B块,会报如下错误:
 a+=1   #UnboundLocalError: local variable 'a' referenced before assignment
UnboundLocalError: local variable 'a' referenced before assignment

# 不注释A块和B块,会正常运行,预期如下:
a_fun:  3
__main__ 4

Process finished with exit code 0
'''

总结:全局变量的使用是为了使我们在一个类或一个函数中使用由函数返回的变量,并进行复杂的计算过程而使用。


而对于一个函数的局部变量,则只在一个函数内部是可使用的,而如果需要跨越不同的函数或者类则需要在基础函数中返回一个该值,在下一个函数中运行其方法才能获取该值进行计算;如果程序不复杂,在一个类中可以解决全局变量会为我们节省不少的时间,以及内存空间。

2、局部变量和全局变量的用法示例:

1)试图访问局部变量例子

# coding:utf-8
def fun(x):
    y=2
    print "乘法的运行结果:", x*y
num1=1
print "初始num1=",num1
fun(num1)
print "y的值是:", y

'''
报错:
Traceback (most recent call last):
  File "/Users/a6/Downloads/PycharmProjects/AB/test_global.py", line 8, in <module>
    print "y的值是:", y
NameError: name 'y' is not defined
原因: 因为试图访问局部变量,但是访问的地方不在该变量y的作用域中
'''

2)示例二


# coding:utf-8
def fun():
    num1=2
    print "函数内修改后num1=",num1
num1=1
print "初始num1=",num1
fun()
print "运行完函数后num1=",num1
'''
输出结果为:

初始num1= 1
函数内修改后num1= 2
运行完函数后num1= 1

分析:可以看到在函数内部对全局变量的修改后,在函数执行完毕,修改的结果是无效的,全局变量并不会受到影响
'''

3)引子


# coding:utf-8
def fun():
    num1*=2
    print "函数内修改后num1=",num1
num1=1
print "初始num1=",num1
fun()
print "运行完函数后num1=",num1

'''
输出结果:
/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/a6/Downloads/PycharmProjects/AB/test_global.py
初始num1= 1
Traceback (most recent call last):
  File "/Users/a6/Downloads/PycharmProjects/AB/test_global.py", line 7, in <module>
    fun()
  File "/Users/a6/Downloads/PycharmProjects/AB/test_global.py", line 3, in fun
    num1*=2
UnboundLocalError: local variable 'num1' referenced before assignment

Process finished with exit code 1
原因:
报错了。这是因为在fun()函数使用了局部变量num1,它只是个跟全局变量同名的局部变量,使用前还是要赋值,
因此再次强调不要这样使用
'''


3)python 2.x中的global关键字

# coding:utf-8
# global关键字
# 如果真的想要在函数体内修改全局变量的值,就要使用global关键字
def fun():
    global num1
    num1=2
    print "函数内修改后num1=",num1
num1=1
print "初始num1=",num1
fun()
print "运行完函数后num1=",num1

'''
输出结果:

初始num1= 1
函数内修改后num1= 2
运行完函数后num1= 2

Process finished with exit code 0

分析:使用global关键字就是告诉python编译器这个变量不是局部变量而是全局变量,其实有点像是"引用"的意思
'''


4)python 3.0中的nonlocal关键字

另一个跟变量相关的关键字nonlocal,字面意思就是指当前的这个变量不是局部变量。nonlocal是Python3.0中新增的关键字,python2.x不支持。

# coding:utf-8
# 以下程序只适合在python3.0以上执行
def fun():
    num2=3
    def fun2(): 
        #global num2   # C块
        nonlocal num2  # D块
        num2*=2
        print("num2=",num2)
    return fun2()

fun()

结果分析:
@1、不加 C块 和 D块 注释块会报如下错误:
UnboundLocalError: local variable 'num2' referenced before assignment
@2、错误的原因跟前面的差不多,就是使用了未定义的局部变量,
然而num2也不是全局变量,只是fun2函数的外层变量,强行使用global定义num2的话同样会报错(不信你试试)
这时候需要使用nonlocal关键字。
@3、使用 global num2 会报如下错误:
NameError: global name 'num2' is not defined
@4、使用 nonlocal num2  就正常啦:
运行结果:
num2=6
如此,程序就能正常执行