Python的全局变量、局部变量、类变量、实例变量介绍

Python的变量分类

全局变量:模块内、所有函数外、所有class外的变量;

局部变量:函数内的变量,class的方法内且不使用self.修饰的变量;

类变量:class内且不在class的方法内;

实例变量:class的方法内且使用self.修饰的变量。

对于面向过程程序设计涉及:

全局变量:模块中函数外的变量。

局部变量:函数中的变量。

若使用类(class)面向OOP涉及:

类变量:class内,不在class的任何方法内。

实例变量:class的方法内且前面使用self.的变量。

局部变量:函数内的变量,class的方法中且前面没有self.的变量。

全局变量:模块内、所有函数外、所有class外。

Python 作用域(scope)和命名空间(namespace)

Python程序中的每个名称(变量名、函数名、类名)都有一个作用域(scope),即它所在的命名空间(namespace)。在它的作用域之外,该名称不存在,任何对它的引用都会导致错误。

每当Python解释器(interpreter)需要计算一个名称(变量、函数等)时,它都会按以下顺序搜索名称:

1.首先局部(L,local)名称空间:自定义函数内部的变量名。

2.外层/封闭(E,enclosing)函数名称空间:如嵌套函数的外层函数中的变量名。【中文在线帮助将enclosing functions译为外层函数,有些资料称为封闭函数】

3.然后是全局(Gglobal)名称空间:如模块中函数外。

4.最后是内置(B,builtins)模块的名称空间:如内置模块预定义的变量名称。

优先顺序: L –> E –> G  –>B。若最后找不到,抛出异常。

【Python命名空间(Namespaces)和作用域(Scopes)】

一、面向过程程序设计(不涉及类)的情况

例子:

n=1

def f():
    n=2  #再删除或注释掉该句看看
    
    def g():
        n=3  #先删除或注释掉该句看看
        print(n)
        
    g()

f()

运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_实例变量

局部变量

在函数调用执行过程中分配的名称称为局部名称,它们对于函数调用来说是局部的。函数的局部名称只存在于与函数调用关联的命名空间中。表现为:

•仅对函数内部的代码可见。

•不干涉函数外部定义的名称,即使它们是相同的。

•仅在函数执行期间存在。它们在函数开始执行之前不存在,在函数完成执行之后也不再存在。

局部变量在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了——即当函数调用完成后,则销毁局部变量,不再有效。例如:

def testA():
    a = 100  # 局部变量
    print(a) #函数体内部访问,能访问到a变量

testA() #调用函数 输出100
print(a) #报错,在函数外不能访问局部变量

 运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_局部变量_02

全局变量,全局变量是在函数外和class外的变量,默认作用域是所在的模块(module)——即程序文件,全局变量和局部变量,名称可以相同,但它们是无关的——对局部作用域变量的修改,全局变量并不会受到影响(不存在生效的 global 或 nonlocal 语句时)。如: 

a = 100  #全局变量a

def testA():    
    print(a)# 访问全局变量a,并打印变量a存储变量
 
def testB():
    a = 50  #局部变量a
    print(a)# 访问局部变量a,并打印其值
 
testA()  #输出:100
testB()  #输出:50
print(a)  #输出:100

运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_开发语言_03

 global 语句

global 语句是作用于整个当前代码块的声明。 它意味着所列出的标识符将被解读为全局变量。简单地说,由global标出的变量是全局变量,例如:


def testB():
    global a  #声明(declaration)a 是global
    a=50
    print(a) 
 
testB()  #输出:50
print(a)  # 使用a不报错,输出:50


运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_python_04


使用global关键字,可以在函数中修改全局变量的值,示例源码如下:


a = 100

def testA():    
    print(a)# 访问全局变量a,并显示
 
def testB():
    global a  #声明(declaration)a 是global
    a=50
    print(a)
 
testA()  #输出:100
testB()  #输出:50
print(a)  #输出:50


运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_开发语言_05


nonlocal 语句

nonlocal语句使列出的标识符引用之前在最近的封闭作用域(enclosing scope)中先前绑定的变量(bound variables),不包括全局变量。简单地说,由nonlocal标出的标识符将被解读为嵌套函数的外层函数中的变量——想修改外层函数中的变量,必须加nonlocal声明,例如

def fun():  
    a=30
    
    def fun2():
        nonlocal a  #声明a是nonlocal
        a=a*2  
        print(a)
        
    return fun2()  

fun() #输出60

二、使用类(class)的情况

Python使用class关键字来定义类,class关键字之后是一个空格,接下来是类的名字,如果派生自其它基类的话则需要把所有父类放到一对圆括号中并使用逗号分隔,然后是一个冒号,最后换行并定义类的内部实现。

实例变量(instance variable)用于每个实例的唯一数据。定义位置类中,所有函数内部:以“self.变量名”的方式定义的变量。

类变量(class variable)用于类的所有实例共享的属性和方法。定义位置类中、所有函数之外。

局部变量,在class的方法(class的函数)中且没有self.的变量。

类变量、实例变量和局部变量示例源码如下:

class Demo:
    Tag = "Tag是类变量"           #Tag是类变量
    def __init__(self, name):    #self表示当前实例对象
        self.DemoName = name   #DemoName是实例变量
 
    def print_name(self):
        ask = "他是谁?"      #ask是局部变量
        print(ask + self.DemoName)  # 局部变量 与 实例变量 拼接
 

d = Demo("Tom")
print(Demo.Tag) #类变量Tag被访问
d.print_name()

运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_python_06

类变量的调用

通过类名访问:类名. 类变量名,也可以先实例化类,使用类的实例化对象调用(此方法不推荐使用):实例对象名.类变量名。例如:

class Person:
    nameC = "小芳"
    ageC = 10
    
    def __init__(self, name, age):
        self.nameI = name
        self.ageI = age
        
#使用类名直接调用类变量
print(Person.nameC)
print(Person.ageC)

#类的实例化对象
p=Person("李晓明",16)
#通过对象名访问类变量
print(p.nameC)
print(p.ageC)
#通过对象名访问实例变量
print(p.nameI)
print(p.ageI)

运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_python_07

实例变量的调用

通过对象名(也叫实例名)访问:对象名. 实例变量,

(1)构造函数__init__()里的成员变量,在类实例化之后,就可以使用

(2)在类里普通函数里的 成员变量,还需要先调用该函数,才能使用该成员变量,否则报错。

例如:

class Person:
    def __init__(self):
        self.name = "小芳"
        self.age = 10
        
    def say(self):
        self.content = "我爱Python"
        
#name、age以及content都是实例变量。Person类的类对象都会包含name和age实例变量。
mary = Person()
print(mary.name)
print(mary.age)
#只有调用了say()方法的类对象才会包含content实例变量。
mary.say()
print(mary.content)

运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_实例变量_08

最后,了解一下类的 命名空间。

当进入类定义时,将创建一个新的命名空间,并将其用作局部作用域,所有对局部变量的赋值都是在这个新命名空间之内。

如果同样的属性(attribute)名称同时出现在实例和类中,则属性查找会优先选择实例。例如:

class Dog:  #定义类

    name = 'canine'         # 类变量

    def __init__(self, nameLocal):
        self.name = nameLocal    # 实例变量,删除或注释掉该句看看
        pass

print(Dog.name)       # 使用类变量

d = Dog('Fido') # 实例化
e = Dog('Buddy') # 实例化
print(d.name)          # 使用实例变量
print(e.name)          # 使用实例变量

运行测试如下:

python类中创建变量为全局变量 python定义在类里的全局变量_python类中的成员变量定义_09

 OK!