python: if __name__ == "__main__" 到底是什么鬼?

61 阅读4分钟

比如有一天我写了个洗脑营销的程序:

def spam1():
	print('还我血汗钱!')

def spam2(guy):
	print(guy + '你不是人!')

def spam3(guy):
	print(guy + '你还我血汗钱!')

def spam4(guy):
	print(guy + '和他的小姨子跑了!')

spam1()
spam1()
spam2('黄老板')
spam3('黄老板')
spam4('黄老板')

定义了4个函数spam1()~spam4(),并且依次调用了这几个函数。

我把这个文件保存成spam.py,运行效果非常好:

E:>python spam.py
还我血汗钱!
还我血汗钱!
黄老板你不是人!
黄老板你还我血汗钱!
黄老板和他的小姨子跑了!

隔壁张三看到这么好的宣传效果,想借我的代码用一下,尤其是想复用我写的几个spam()函数。

他把我的spam.py拿去以后,另外写了一个zhangsanSpam.py,在其中用import导入了spam.py,并且传了他自己想骂的对象'陈老板'作为参数:

import spam

spam.spam1()
spam.spam1()
spam.spam2('陈老板')
spam.spam3('陈老板')
spam.spam4('陈老板')

结果运行的时候悲剧了,他也跟着把黄老板骂了一遍:

E:>python zhangsanSpam.py
还我血汗钱!
还我血汗钱!
黄老板你不是人!
黄老板你还我血汗钱!
黄老板和他的小姨子跑了!
还我血汗钱!
还我血汗钱!
陈老板你不是人!
陈老板你还我血汗钱!
陈老板和他的小姨子跑了!

在zhangsanSpam.py里通过import spam导入spam.py,会执行一遍spam.py里的所有代码。这里面有张三想要的几个spam()函数的定义,但是他不想要的骂黄老板的代码也跟着运行了。

有没有啥办法在spam.py里作区分呢?我希望实现这样的效果:

  • 如果spam.py被拿来直接运行,就执行那几个spam()函数
  • 如果spam.py被用来当作写好的[函数库],导入到其他文件里面去,就不执行那几个spam()函数

这就需要用到__name__了。试试看在spam.py里显示__name__的值:

  def spam1(): 
      print('还我血汗钱!')
  def spam2(guy): 
      print(guy + '你不是人!')
  def spam3(guy): 
      print(guy + '你还我血汗钱!') 
  def spam4(guy): 
      print(guy + '和他的小姨子跑了!') 
 print(__name__)

直接运行spam.py,可以看到__name__的值是'__main__'

E:>python spam.py
__main__

运行zhangsanSpam.py,它会变成'spam',这是导入的库spam的名字。注意它显示在第一个“还我血汗钱!”的前面:

E:>python zhangsanSpam.py
spam
还我血汗钱!
还我血汗钱!
陈老板你不是人!
陈老板你还我血汗钱!
陈老板和他的小姨子跑了!

由此我们得到了区分的方法——

  • 定义函数的部分原封不动
  • “直接运行此文件时执行,但把此文件当作函数库导入的时候不运行”的代码放进[if分支]里。判断条件是__name__是否等于'__main__'

据此修改一下spam.py:

def spam1(): 
    print('还我血汗钱!') 
def spam2(guy): 
    print(guy + '你不是人!') 
def spam3(guy): 
    print(guy + '你还我血汗钱!') 
def spam4(guy): 
    print(guy + '和他的小姨子跑了!') 
if __name__ == '__main__': 
    spam1() 
    spam1() 
    spam2('黄老板') 
    spam3('黄老板') 
    spam4('黄老板')

这样我自己可以照常用它骂黄老板:

E:>python spam.py
还我血汗钱!
还我血汗钱!
黄老板你不是人!
黄老板你还我血汗钱!
黄老板和他的小姨子跑了!

张三拿去当作函数库,也不会骂错人了:

E:>python zhangsanSpam.py
还我血汗钱!
还我血汗钱!
陈老板你不是人!
陈老板你还我血汗钱!
陈老板和他的小姨子跑了!

或者,如果你想趁机暗算张三这种白嫖怪,只需要再加一个判断:

def spam1(): 
    print('还我血汗钱!') 
def spam2(guy): 
    print(guy + '你不是人!') 
def spam3(guy): 
    print(guy + '你还我血汗钱!') 
def spam4(guy): 
    print(guy + '和他的小姨子跑了!') 
if __name__ == '__main__': 
    spam1() 
    spam1() 
    spam2('黄老板') 
    spam3('黄老板') 
    spam4('黄老板') 
if __name__ == 'spam': 
    print('我是个疯子,整天满嘴跑火车。不信你看:')

张三拿去,哼哼……让你白嫖!让你白嫖!

E:>python zhangsanSpam.py
我是个疯子,整天满嘴跑火车。不信你看:
还我血汗钱!
还我血汗钱!
陈老板你不是人!
陈老板你还我血汗钱!
陈老板和他的小姨子跑了!