最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【整理】Python中变量的作用域(variable scope)

Python crifan 17431浏览 0评论

此文目的

此文主要讨论和总结一下,Python中的变量的作用域(variable scope)。

目的在于,通过代码,图解,文字描述,使得更加透彻的了解,Python中的变量的作用域;

以避免,在写代码过程中,由于概念不清晰而导致用错变量,导致代码出错和变量含义错误等现象。

如有错误,欢迎指正。

 

解释Python中变量的作用域

Python变量作用域的解释之代码版

所用的示例代码,主要来自于:

【整理】Python中:self和init__的含义 + 为何要有self和__init__

中的:

#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
Function:
【整理】Python中:self和init__的含义 + 为何要有self和__init__
https://www.crifan.com/summary_the_meaning_of_self_and___init___in_python_and_why_need_them

Author:     Crifan
Verison:    2012-11-27
-------------------------------------------------------------------------------
"""

#注:此处全局的变量名,写成name,只是为了演示而用
#实际上,好的编程风格,应该写成gName之类的名字,以表示该变量是Global的变量
name = "whole global name";

class Person:
    name = "class global name"

    def __init__(self, newPersionName):
        #self.name = newPersionName;
        
        #此处,没有使用self.name
        #而使得此处的name,实际上仍是局部变量name
        #虽然此处赋值了,但是后面没有被利用到,属于被浪费了的局部变量name
        name = newPersionName;

    def sayYourName(self):
        #此处,之所以没有像之前一样出现:
        #AttributeError: Person instance has no attribute 'name'
        #那是因为,虽然当前的实例self中,没有在__init__中初始化对应的name变量,实例self中没有对应的name变量
        #但是由于实例所对应的类Person,有对应的name变量,所以也是可以正常执行代码的
        #对应的,此处的self.name,实际上是Person.name
        print 'My name is %s'%(self.name); # -> class global name
        print 'name within class Person is actually the global name: %s'%(name); #-> whole global name
        print "only access Person's name via Person.name=%s"%(Person.name); # -> class global name

def selfAndInitDemo():
    persionInstance = Person("crifan");
    persionInstance.sayYourName();
    print "whole global name is %s"%(name); # -> whole global name
    
###############################################################################
if __name__=="__main__":
    selfAndInitDemo();

 

Python变量作用域的解释之图解版

下面来图形来解释一下:

variable effective domain

 

Python变量作用域的解释之文字版

再用文字简要描述就是:

全局变量(Global variable)

不论是其他普通函数中,还是Class类中,都是可以通过对应的变量名,而可以直接引用的。

局部变量(automatic variable)

对于函数内,包括类Class的函数内,普通的变量,都是自动临时变量

 

此处插播背景知识:

变量的优先级关系

普通局部变量和全局变量的作用域,最核心的区别在于:

内部变量的优先级大于外部变量

此处即,(函数内的)局部变量,优先级大于,(外部的)全局变量

换句话说:

A。如果函数内部,出现了和全局变量同名的变量,则说明是局部变量;

B。如果,函数内,没有同名的局部变量的情况下,对应的变量,则是全局变量。

这个变量的优先级关系,不仅针对与Python语言,几乎其他所有语言,都适用,比如C/C++/C#等等。

 

所以,上面示例中的__init__中的name,不是全局变量:

name = “whole global name”;

中的name而是,局部变量;

其中,此处是属于那种,Python(和,或其他特殊)语言所特有的,无需声明变量,就可以直接使用的情况。

即局部变量name,并没有声明,但是就直接拿过来使用,通过:

name = newPersionName;

在初始化,设置为对应的名字,此处即”crifan”了。

 

类(Class)的变量

类的变量,在类的范围内,只能通过

ClassName.PropertyName

或者说

ClassName.VariableName

去访问,当前类ClassName的变量PropertyName

例子中,就是通过

Person.name

去访问类Person中的变量name的值的。

 

示例(Instance)的变量

示例中的变量,理论上,是用

InstanceObject.PropertyName

去访问的。

而此处,由于Python中,默认的,约定俗成的写法,把类的函数的第一个参数的名字,定义为Instance变量,且名字叫做self,所以,就变成了:

self.PropertyName

了。

所以,上述在类的函数中,想要访问Instance的变量的话,就是通过

self.name,去访问类Person的示例self中的变量name了。

 

总结

所以,想要彻底了解变量的作用域;

还是要多多写代码自己测试。

并且最好具有其他不同语言的相关背景知识,以便更加方便去实现横向对比,实现融会贯通,举一反三的效果。

转载请注明:在路上 » 【整理】Python中变量的作用域(variable scope)

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (5)

  1. 代码第38行的name按照LEGB规则,不是应该是class global name吗? 想要引用第19行的name,必须加person.name吗? 这不是违反LEGB规则吗?
    li ye8年前 (2017-03-29)回复
  2. 所以,上面示例中的init中的name,不是全局变量: name = “whole global name”; 中的name而是,局部变量; 这里的name不是全局变量么?
    xiaoming8年前 (2016-11-15)回复
  3. 谢谢您的分享,真的很感谢
    苏打9年前 (2016-06-22)回复
  4. InstandceObject.PropertyName 笔误 应改为InstanceObject.PropertyName
    leox10年前 (2015-02-12)回复
88 queries in 0.185 seconds, using 22.24MB memory