文章目录

  • @[TOC](文章目录)
  • 什么是内置类属性
  • 一、\__dict__ 的用法
  • 二、\__name__的用法
  • 三、\__file__的用法

什么是内置类属性

当python创建一个类之后,系统就自带了一些属性,叫内置类属性。这些属性名用双下划线包括并与普通属性名区分。通常的属性包括:

属性

含义

_name_

当前定义的【类】的名字

_module_

【类或对象】所属的模块名

_dict_

【类或对象】的属性(包含一个字典,由类的数据属性组成)

_doc_

【类或对象】的文档字符串 - 一般写在class 类下面

base

当前【类】的父类

bases

当前【类】所有父类构成的元组

一、_dict_ 的用法

__dict__可以作用在文件、类或者类的对象上,最终返回的结果为一个字典。

对于类而言,类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类__dict__里的;对于类的对象而言,对象的__dict__中存储了关于self.xxx变量的信息:

class TestName:
    a = 2
    b = 2

    def __init__(self,c):
        self.a = 0
        self.b = 1
        self.c = c

    def test1(self):
        print("a normal func")

    @staticmethod
    def static_test(self):
        print("a static class")

    @classmethod
    def class_test(self):
        print("a class func")

o = TestName(2)
print(TestName.__dict__)
print(o.__dict__)

结果:
{'__module__': '__main__', 'a': 2, 'b': 2, '__init__': <function TestName.__init__ at 0x000001EFA81DD268>, 'test1': <function TestName.test1 at 0x000001EFA81DD1E0>, 'static_test': <staticmethod object at 0x000001EFA801B390>, 'class_test': <classmethod object at 0x000001EFA801B320>, '__dict__': <attribute '__dict__' of 'TestName' objects>, '__weakref__': <attribute '__weakref__' of 'TestName' objects>, '__doc__': None}
{'a': 0, 'b': 1, 'c': 2}

利用__dict__可以给运行中的对象添加新的属性,接上例:

o.__dict__['new'] =10 

结果:
{'a': 0, 'b': 1, 'c': 2, 'new': 10}

二、__name__的用法

在很多 Python程序里,经常会看到这样的一段代码:

if __name__ == '__main__':
    main()

但很多人对这个内置变量的具体含义并不清楚。作为 Python 的内置变量,__name__变量还是挺特殊的。它是每个 Python 模块必备的属性,但它的值取决于你是如何执行这段代码的。

在许多情况下,你的代码不可能全部都放在同一个文件里,或者你在这个文件里写的函数,在其他地方也可以用到。为了更高效地重用这些代码,你需要在 Python 程序中导入来自其他文件的代码。所以,在__name__ 变量的帮助下,你可以判断出这时代码是被直接运行,还是被导入到其他程序中去了。当你直接执行一段脚本的时候,这段脚本的__name__ 变量等于__main__,当这段脚本被导入其他程序的时候__name__ 变量等于脚本本身的名字。

例如,我们有一个脚本名叫nameScript.py

def myFunction():
    print('变量 __name__ 的值是 ' + __name__)

def main():
    myFunction()

if __name__ == '__main__':
    main()

运行结果:
变量 __name__ 的值是 __main__

在所有其他代码执行之前__name__变量就被设置为__main__了。在此之后,通过执行 def 语句,函数 main() 和 myFunction() 的本体被载入。接着,因为这个 if 语句后面的表达式为真 true,函数 main() 就被调用了。而 main() 函数又调用了myFunction(),打印出变量的值__main__ 。

python中为什么类的属性不在内部 python类的内置属性_Python

新建一个 importingScript.py 文件,将 nameScript.py 作为一个模组导入,重用这个 myFunction() 函数:

#importingScript.py内容

import nameScript as ns
ns.myFunction()

运行结果:
变量 __name__ 的值是 nameScript

为什么会出现这个结果?变量的值变成了 nameScript,也就是我们导入的模块的名称。这是因为有了两个不同的作用域:一个是 importingScript 的,一个是 nameScript 的:

python中为什么类的属性不在内部 python类的内置属性_python中为什么类的属性不在内部_02


在 importingScript.py 里__name__ 变量就被设置为 main。当导入 nameScript 的时候,Python 就在本地和环境变量 PATH 指向的路径中寻找对应名称的 .py 文件,

找到之后,将会运行导入的文件中的代码。

但这一次,在导入的时候,它自身的__name__ 变量就被设置为了 ‘nameScript’,接下来还是一样,函数 main() 和 myFunction() 的本体被载入。然而,这一次 if 语句后面的表达式结果为假 false,所以 main() 函数没有被调用。

导入完毕之后,回到 importingScript.py 中。现在 nameScript 模块中的函数定义已经被导入到当前的作用域中,于是我们通过 ns.myFunction() 的方式调用模块中的函数,
这个函数返回的是模块内的变量的值 ‘nameScript’。

但是如果在 importingScript 中打印__name__ 变量的值,那直接执行 importingScript 的时候,它也会输出__main__。原因在于,这个变量是在 importingScript 的作用域中的,如果没有特殊设定,默认为__main__。

import nameScript as ns
ns.myFunction()
print(__name__)

运行结果:
变量 __name__ 的值是 nameScript
__main__

三、__file__的用法

内置变量__file__比较容易理解,它表示显示文件当前的位置。这里的文件当前位置值得是执行这个脚本时,脚本所在路径相对于执行路径所在的路径。比如有一个脚本test.py在路径/home/user/test/下,如果我们在/home/user/test/下执行:

print(__file__)

运行结果:
test.py

如果我们在/home/user下执行:

print(__file__)

运行结果:
test/test.py

这里要注意,如果执行命令时使用绝对路径,__file__就是脚本的绝对路径。如果使用的是相对路径,__file__就是脚本的相对路径。

另外,在交互式环境中,会爆出异常。因为此时__file__并未生成。使用jupyter时,__file__也是无效的。会报错:name ‘_file_’ is not defined

由于用__file__来表示文件当前位置会存在绝对路径和相对路径的问题,我们还可以使用sys模块中的sys.argv[0]来表示执行的当前文件所在的路径,这一参数返回当前文件的绝对路径加上文件名。