python笔记(七)变量

2018-12-15  本文已影响2人  艺术家可达鸭

变量/函数下划线的作用

变量作用域

  1. Local:函数/方法/列表推导式/类
  2. Enclosing:外层函数/方法
  3. Global:模块
  4. Built-in:Python 的 builtins 模块。全局变量中有一个名为__builtins__的模块对象

以 L –> E –> G –>B 的规则查找
Python除了 def/class/lambda/列表推导式/类 外,其他如: if/elif/else/ try/except for/while 是没有名字空间的

坑1:自由变量可访问不可赋值

自由变量就是不在当前作用域中的变量

变量的获取是按上述规则查找,但是对于变量的赋值(i=1 这种),只要该变量在当前作用域内没有被定义,就会定义一个新变量,除非使用 global,nonlocal 关键字

global 关键字:不要定义新变量,使用全局的同名变量
nonlocal 关键字:不要定义新变量,使用外层函数的同名变量
globals():当前模块全部的全局变量
locals():当前名字空间的所有变量,一般就是某个函数的全部变量

def func():
    global tmp
    tmp=123
# 如果全局变量存在,则将其赋值为 123
# 如果全局变量不存在,则创建一个全局变量,并赋值为 123

坑2:Enclosing 作用域

Enclosing 是函数定义时的嵌套作用域,而不是函数调用时的。
这其实不算是一个坑。我本身代码写得少,而我在 Java 中很少有【一个方法调用同一个类中的其它方法】的情况,所以对这种比较陌生。
比如下面这段代码是错误的

def say():
    print(s) # s 没有被定义,不能使用

def main():
    s='hello'
    say()

坑3:类的局部作用域

类代码块是局部作用域,和方法的作用域是同级别的,不是嵌套的,所以以下代码是错误的

class C():
    s=1
    def say(self):
        print(s) # s 没用被定义,必须使用 C.s

坑4:类需要在定义完成后才能使用

任何变量都要先定义后使用,这自不必说,但是以下情况常常使我忘记这点。

class C():
    s=1
    ss=[ C.s + i for i in range(10) ] # 不能使用 C.s,因为类还没定义完,还没有 C 这个类
    ss=[ s + i for i in range(10) ] # 不能使用 s,因为列表推导式有自己的作用域

坑5:UnboundLocalError

下面的代码是错误的,i 已经在 Local 中被定义,所以不会去 Global 中查找,但是 Local 中 i 的使用先于定义,故报错。
Java 中也有这个坑。

i = 2
def test():
    print(i)
    i = 1

dir() 与 __dict__ 的区别

__dict__:在当前实例中定义的成员,就是用self.value=value定义的成员。对于类就是类中定义的成员,对于函数方法,就是空,啥都没有
dir():当前实例所有能访问到的成员,对于实例而言,它还能访问到它的类中的成员。类成员并不是类私有的,而是所有实例共享的
dir() 获得的是包含属性名的列表;__dict__获得的是包含属性名和属性值的字典
globals()和locals():类似于__dict__,只不过这两个是函数,而__dict__是属性

魔术变量的访问顺序

魔术变量如果不指定其所属的对象,那就是指 Global 中的魔术变量

"""
module
"""

def main():
    """
    main()
    """
    # __doc__='new module' 这一行将修改 Global 中的 __doc__ 属性
    print(__doc__, main.__doc__, __builtins__.__doc__, sep='\n')

if __name__ == '__main__':
    main()
上一篇下一篇

猜你喜欢

热点阅读