I am LAZY bones? AN ancient AND boring SITE

为什么python里要 if __name__ == ‘__main__’:

尽管python允许你像shell脚本一样,把大段的代码堆积着写,但是,很多python入门的书,都会建议你把代码写成一个函数,然后在最后面统一调用,例如这样:

def main():
    #具体代码
 
if __name__ == '__main__':
    main()

很多文章都会说这个是由于代码风格之类的原因,但是其实,不这样写,有时候也是会直接导致出错的。
举个例子,打开《A Byte of Python》的类变量那节,可以这里看在线版本,然后把中间的那示例代码复制下来,运行,可以看到,确实能得到预期正确的结果。
但是,现在把那代码里的所有“swaroop”换成“xxx1”,再把所有“kalam”换成“yyy1”,再运行,就会在程序运行的最后时刻,得到这么一个奇怪的错误(Python 2.6.5下实验):
Exception AttributeError: "'NoneType' object has no attribute 'population'" in > ignored
也就是说,换了个变量名,程序就出错了。。。
究其原因,应该是python在最后析构所有类和对象的时候,并没有处理这些对象之间的依赖关系,而是根据变量名来决定某种顺序操作了。从而导致Person类本身,先于yyy2被干掉了,所以在解构yyy2的时候,执行它的__del__()方法,却发现父类都已经没有了~~
这应该确实算是python解析器的bug,但是,如果那把这个例子里的所有class Person以外的代码,写到一个main()函数里,再通过上述方法调用的话,就不会发生这种错误了。
所以,大家最好还是别太在意多几行代码,养成这个好习惯吧。

要深究此错误的原因,可以看官方文档里的描述,并在这里讨论。

最后修改时间: 2010年05月31日 18:52

本文章发表于: 2010年05月31日 18:52 | 所属分类:编程相关. | 您可以在此订阅本文章的所有评论. | 您也可以发表评论, 或从您的网站trackback.

13 个评论 关于: “为什么python里要 if __name__ == ‘__main__’:”

  1. maonx 在 2010年05月31日 19:27 说:回复

    以前还真没发现,以后我看要加上了

  2. est 在 2010年05月31日 19:50 说:回复

    有一次看comp.lang.python里有人说 if ‘__main__’ == __name__ 效率更高。。。

    • lonelinsky 在 2010年06月01日 18:36 说:回复

      这个有理由么?我觉得只是从c/c++继承过来的为了防止误写 – – 囧

  3. Iven 在 2010年05月31日 20:39 说:回复

    好像DIP里面说主要是防止后面的代码被import……

    • Dig 在 2010年06月02日 13:46 说:回复

      同意这个,而且有某位同学遇到过这种问题。

  4. bones7456 在 2010年06月01日 08:34 说:回复

    呵呵,看来原因还不少。不过效率为什么会高呢?

  5. 依云 在 2010年06月01日 12:43 说:回复

    对于用 main() 的程序,我曾先 import 进来,改点东西,然后再调用 main()。如果不这样,那就只能去改它的源代码了。

  6. googya 在 2010年06月01日 16:31 说:回复

    没有问题啊,我的是Python 2.5的,windows下的

  7. lonelinsky 在 2010年06月01日 18:16 说:回复

    win python2.6.5,确实有这个问题,不明白为什么用函数的时候析构就没有问题了- – 因为变成局部变量了?不析构就不析构,反正最后会挂?

    还有est说的那个效率更高的问题,我觉得那个只是为了防止误写吧,不过python是不支持行内赋值的,所以不存在误写的问题吧,至于效率,应该是一样的吧 – – 具体不太清楚了~~

    • bones7456 在 2010年06月01日 20:06 说:回复

      用函数写的话,函数结束 发生在 整个文件结束 之前。析构那些变量 发生在 函数结束 的时候。 析构类本身 发生在 文件结束 的时候。所以能保证 变量 在 类 被析构之前析构掉。这是我理解,呵呵。

  8. Tusooa 在 2010年06月21日 17:52 说:回复

    [tlcr: 0] [21/06/2010 17:44:13] [tusooa@tusooa-laptop] [~]
    >> python -V
    Python 2.6.5
    [tlcr: 0] [21/06/2010 17:44:16] [tusooa@tusooa-laptop] [~]
    >> python /tmp/test
    (Initializing Swaroop)
    Hi, my name is Swaroop.
    I am the only person here.
    (Initializing Abdul Kalam)
    Hi, my name is Abdul Kalam.
    We have 2 persons here.
    Hi, my name is Swaroop.
    We have 2 persons here.
    Swaroop says bye.
    There are still 1 people left.
    Abdul Kalam says bye.
    I am the last one.
    [tlcr: 0] [21/06/2010 17:44:21] [tusooa@tusooa-laptop] [~]
    >> python /tmp/test
    (Initializing Swaroop)
    Hi, my name is Swaroop.
    I am the only person here.
    (Initializing Abdul Kalam)
    Hi, my name is Abdul Kalam.
    We have 2 persons here.
    Hi, my name is Swaroop.
    We have 2 persons here.
    Swaroop says bye.
    There are still 1 people left.
    Abdul Kalam says bye.
    Exception AttributeError: “‘NoneType’ object has no attribute ‘population'” in <bound method Person.__del__ of > ignored

    确实很奇怪。
    但是用其它的变量名(如a,b)就没问题。

  9. vzomik 在 2010年06月25日 20:23 说:回复

    以前看到这个标题,直接漂过,因为不懂。
    现在回来再看,懂了~谢谢。

  10. 淡淡的糊涂 在 2013年05月22日 11:14 说:回复

    试验了你说的方法,但是没有报错。环境是windows xp系统下python 2.7.5 shell。请问为什么没有出现你上面所说的错误呢?

发表评论