文章目录
- @[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__ 。
新建一个 importingScript.py 文件,将 nameScript.py 作为一个模组导入,重用这个 myFunction() 函数:
#importingScript.py内容
import nameScript as ns
ns.myFunction()
运行结果:
变量 __name__ 的值是 nameScript
为什么会出现这个结果?变量的值变成了 nameScript,也就是我们导入的模块的名称。这是因为有了两个不同的作用域:一个是 importingScript 的,一个是 nameScript 的:
在 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]来表示执行的当前文件所在的路径,这一参数返回当前文件的绝对路径加上文件名。