if __name__ == ‘__main__’: 的作用是:让一个文件既可以作为可以导入的模块,也可以作为独立的程序直接运行。当这个文件被直接执行时,if __name__ == ‘__main__’后面的代码会被执行;但如果该文件是被导入的,if __name__ == ‘__main__’后面的代码则不会被执行。
一、if __name__ == ‘__main__’: 究竟起什么作用
一个python文件通常有两种使用方法,名列前茅是作为脚本直接执行,第二是 import 到其他的 python 脚本中被调用(模块重用)执行。因此 if __name__ == ‘__main__’: 的作用就是控制这两种情况执行代码的过程,在 if __name__ == ‘__main__’: 下的代码只有在名列前茅种情况下(即文件作为脚本直接执行)才会被执行,而 import 到其他脚本中是不会被执行的。
作为脚本直接执行:
假设我们有个叫做 demo.py 的 Python 文件,其中包含了一些函数定义和变量声明。在 demo.py 文件末尾加入如下代码:
if __name__ == '__main__':
print('这个文件正在被直接执行!')
当我们在命令行中输入 python demo.py 并运行时,会输出”这个文件正在被直接执行!”。
作为模块导入:
假设我们有另一个叫做 test.py 的 Python 文件,想要调用 demo.py 中的某些函数。在 test.py 中导入 demo.py,并调用其中的函数:
import demo
result = demo.add(1, 2)
print(result)
如果 demo.py 不包含 if __name__ == ‘__main__’ 语句,当我们运行 test.py 时会先输出”这个文件正在被直接执行!”,然后才输出 add 函数的调用结果,这并不是我们所期望的。而如果在 demo.py 中加入 if __name__ == ‘__main__’ 语句,它只会在 demo.py 直接被执行时输出”这个文件正在被直接执行!” ,当 demo.py 被 test.py 导入时则不会输出。这样可以避免在调用模块时不必要的代码重复执行,使代码更加简洁和高效。
二、python中其他的特殊变量
除了 __name__ 之外,Python 中还有一些类似的特殊变量,它们也以双下划线开头和结尾。以下是一些比较常用的类似的特殊变量:
1、__all__
python模块中的__all__,可用于模块导入时限制,如:
from module import *
此时被导入模块若定义了__all__属性,则只有__all__内指定的属性、方法、类可被导入。若没定义,则导入模块内的所有公有属性,方法和类。
在别的模块中,导入该模块时,只能导入__all__中的变量,方法和类:
__all__ = ('A', 'func')
class A():
def __init__(self, name, age):
self.name = name
self.age = age
class B():
def __init__(self, name, id):
self.name = name
self.id = id
def func():
print('func() is called!')
def func1():
print('func1() is called!')
test.py中定义了__all__属性,只能导入__all__中定义的属性,方法和类:
from test import *
a=A('python','24')
print(a.name,a.age)
func()
#func1() #NameError: name 'func1' is not defined
#b=B('python',123456) #NameError: name 'B' is not defined
2、__slots__
Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性范围:
class P(object):
__slots__ = ("name", "age")
pass
3、__init__()
构造函数,创建实例的时候,可以调用init方法做一些初始化的工作,如果子类重写了init,实例化子类时,则只会调用子类的init,此时如果想使用父类的init,可以使用super函数,如下:
class P(object):
def __init__(self, name, score):
self.name = name
self.score = name
class C(P):
def __init__(self, name, score, age):
super(C, self).__init__(name, score)
self.age = age
4、__new__()
注意:__init__是实例创建之后调用的名列前茅个方法,而__new__更像构造函数,它在__init__之前被调用。另外,__new__方法是一个静态方法,名列前茅参数是cls,__new__方法必须返回创建出来的实例。
例如,用__new__实现单例模式:
class Singleton(object):
def __new__(cls):
# 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
obj1 = Singleton()
obj2 = Singleton()
obj1.attr1 = 'value1'
print(obj1.attr1, obj2.attr1)
print(obj1 is obj2)
5、__repr__()
是给机器用的,在Python解释器里面直接敲对象名在回车后调用的方法。(用于调试)
# test.py
class P(object):
def __str__(self):
return "__str__ called"
def __repr__(self):
return "__repr__ called"
p = P()
__str__和__repr__的区别:
>>> from test import p
>>> p
__repr__ called
>>> print p
__str__ called
6、__exit__
这两个方法是用于支持with语句的上下文管理器。例如让文件句柄支持with语法的实现:
class File(object):
def __init__(self, file_name, method):
self.file_obj = open(file_name, method)
def __enter__(self):
return self.file_obj
def __exit__(self, type, value, traceback):
self.file_obj.close()
with File('demo.txt', 'w') as opened_file:
opened_file.write('Hola!')
延伸阅读1:python的内置函数有哪些
- 类型转换函数:int()、float()、str()、bool()、list()、tuple()、set()、dict()、bytes()、bytearray()、memoryview()等。
- 数字运算函数:abs()、round()、pow()、min()、max()等。
- 列表和元组操作函数:len()、sorted()、reversed()、sum()、zip()、enumerate()、map()、filter()等。
- 字符串操作函数:strip()、split()、join()、replace()、format()、find()、index()等。
- 文件和目录操作函数:open()、read()、write()、close()、os.mkdir()、os.path.join()等。
- 其他函数:print()、input()、range()、dir()、type()、id()、help()、isinstance()、callable()等。