天天看点

[Python内置函数-1] : locals / globals / vars / dir

根据官方文档 :

1.locals()

    返回包含当前作用域的局部变量的字典。

2.globals()

    返回包含当前作用域的全局变量的字典。

3.vars([object])

    没有参数的情况下,返回值与locals()相同。

    传入一个参数的情况下,调用该参数(model, class, instance)中自带的__dict__属性。

object.__dict__

    用于存储对象的属性的字典。

    __dict__属性本身是只读的,该属性类型为dictproxy而不是dict。

    你要设__dict__中的值,可以使用  object.setattr(object, name, default=None) 

4.dir([object])

    没有参数的情况下,返回当前本地作用域(local scope)内的名称列表(等同于返回locals().keys())。

    传入一个参数,则返回一个以字母顺序排序的包含给定对象属性以及可调用属性的列表

    若对象中有一个名为__dir__的方法则会被其调用,

    否则按dir()默认逻辑返回:

    ·     如果对象是模块对象,则该列表包含模块的属性。

    ·     如果对象是类型或类对象,则该列表包含其属性,并递归地包含其基类的属性。

    ·     如果是其他情况,则该列表包含对象的属性、类的属性,以及递归其类的基类的属性。

Python中命名空间(作用域)的概念

    在理解上述内置函数的使用方法之前我们先要了解Python关于作用域的一些概念

    Python创建,改变或查找变量名都是在所谓的命名空间(保存属性的地方)中进行的。所以在python中讨论的作用域就是

    命名空间。也就是说。在代码中变量名被赋值的位置决定了这个变量名能被访问到的范围。

作用域法则

    ·全局作用域的作用范围仅限于单个文件

    ·每次对函数的调用都创建一个新的本地作用域

    ·赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量(在def 中用global定义的变量 )

    ·所有其他的变量名都可以归纳为本地,全局或内置的。

变量名解析

    对于一个def语句:

    ·变量名分为三个作用域进行查找:本地 -> 函数内(如果有的话) -> 全局 ->内置

    ·默认情况下,变量名赋值会创建或改变本地变量

    ·全局声明和非本地声明将赋值的变量名映射到模块文件内部的作用域

LEGB法则(Python变量名解析机制):

    ·当在函数中使用未被认证的变量名时,Python搜索4个作用域[ 本地作用域(Local),之后时上层结构中的def或lambda的       本地作用域(Enclose)(如果有的话),再之后时全局作用域(Global),最后是内置作用域(in-Bulid)]并且在第一处能     找到这个变量名的地方停下来,若没找到则报错。

     ·当在函数中给一个变量名赋值时(而不是在表达式中对其进行引用),Python总是创建或改变本地作用域的变量名,除非它  已经声明为全局变量。

    ·当在函数之外给变量名赋值时(也就是,在一个模块文件的顶层,或者是在交互提示模式下),本地作用域与全局作用域(这是模块的命名空间)是相同的。

    下面来个例子:

# Global scope
X = 1

def func():
    # Enclose scope
    Y = 2
    
    def in_func():
        # Local scope
        Z = 3
           

    按上述代码中in_func()为本地作用域的话,在func()中设置的变量对于in_func()就是上层结构的本地作用域,而在此模块的顶  层(X变量赋值的位置)就是全局作用域了,而对于可在模块中随时调用的内置函数就在内置作用域中了。

内置函数详解

    那通过上面的描述应该已经大致了解了Python在作用域的相关概念。那现在回来看看 locals / globals / vars / dir 这些内置   函数。

    对于globals()而言在函数中的任意位置调用都是返回保存全局属性 键值对 的字典。

globals()中有什么:

>>> globals()
{'__name__':'__main__', '__doc__':None, '__package__':None, '__loader__':<class '_frozen_importlib.BuiltinImporter'>, 
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
           

上面打印的就是model(模块)的初始属性了。

model.__name__ 代码运行在当前模块时值为"__main__",模块被调用时为其模块的名称。

model.__doc__    在该模块的开头有编写模块文档时,其值为模块文档。

model.__package__ 代码运行在当前模块时值为 None, 模块被调用时为其模块的上级文件夹的路径。

model.__loader__ 加载器(有兴趣可以自行了解)

model.__annotations__ 该模块中的所有注释。

model.__builtins__ 封装内置函数的模块

之后你在全局作用域中添加变量或导入模块都会在,全局命名空间中显示。

如:

>>> import re
>>> x = 1
>>> globals()
{'__name__':'__main__', '__doc__':None, '__package__':None, '__loader__':<class '_frozen_importlib.BuiltinImporter'>,
'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 
're': <module 're' from 'E:\\Python\\Python37\\lib\\re.py'>, 'x': 1}