从__name__=='__main__'说到__builtin__

一、__name__

我们在写好代码进行自测的时候一般会先写这样一行代码:

# inter_method

if __name__ == ‘__main__‘:

为什么呢,可能并不是所有人都考虑过,这个就类似与C语言中的main一样,是一个函数的入口,python写的各个module都可以包含这样一个入口,但是在本module执行的时候,__name__就是__main__,而被导入的时候__name__就是module的名称,所以上面那行代码可以保证我们的测试代码只在本module生效而在被导入时并不执行,先看下面的代码print出的值就是__main__。

# inter_method

  1. def inter():
        print(__name__)

    if __name__ == ‘__main__‘:
        inter()  # __main__

如果被引用呢,我们从外部模块导入inter方法,看下面的代码:

# outer_method

  1. import inner_method

    if __name__ == ‘__main__‘:
        print __name__  # __main__
       
    inner_method.inter()  # inner_method

原文件打印的就不再是__main__了,所以测试代码不会执行。

有人会说,我导入时候不是就已经知道模块名了吗,为什么还要通过__name__来获取,其实有时候我们不一定知道,比如我们在中间导入的时候把模块名as成了其他名称,另一个模块再从这里导入我们就不知道原始的模块名了,比如:

# outer_method

  1. import inner_method as inter

# another

  1. from outer_method import inter

    if __name__ == ‘__main__‘:
        print __name__  # __main__
        print inter.__name__  # inner_method

在这种情况下,在another中我们不知道原始模块名的,但是__name__确是知道的。

__name__在模块中是代表module名,在类中代表类名,在方法中代表方法名,看下面的代码:

# inter_method

  1. class Test(object):
        def __init__(self):
            print ‘%s,%s‘ % (‘class‘, Test.__name__)

    def func(self):
            print ‘method %s‘ % Test.func.__name__

    def inter():
        obj = Test()
        obj.func()

    if __name__ == ‘__main__‘:
        inter()  # class,Test, method func

返回的结果是类和方法的名称,但是方法名称也不一定和你看到的一致,__name__会反应这一变化,比如被装饰的方法名称就会有变化:

# inter_method

  1. def dec(func):
        def dec_method(*args, **kwargs):
            func(*args, **kwargs)

    return dec_method

    class Test(object):
        def __init__(self):
            print ‘%s,%s‘ % (‘class‘, Test.__name__)

    @dec
        def method(self):
            print ‘method %s‘ % Test.method.__name__

    def inter():
        obj = Test()
        obj.method()

    if __name__ == ‘__main__‘:
        inter()# class,Test, method dec_method

可以看到,方法名并不是原来的method了,而是由于装饰器的原因变成了dec_method。

二、module

上面在介绍__name__的时候提到了module,在Python中,一个.py文件就构成一个module。通过module,你可以调用其它文件中的程序。我们是通过import 或import a as b的形式来引入module,以通过module.object的方式来调用引入模块中的某个对象,Python会在以下路径中搜索它想要寻找的模块:程序所在的文件夹;标准库的安装路径;操作系统环境变量PYTHONPATH所包含的路径。

有一点需要关注,某些时候他会影响你的代码,即import导入的是一个module,你通过module.object引用的对象仍然是属于原module的,但是你使用from module import object的时候是直接将该object导入到了本module,他成了当前module的一部分。我们看个例子:

  1. # config.py
    param = 100
  1. # inner_method.py
    import config
    config.param = 200
  1. # outer_method.py
    import inner_method as inter
    import config

    if __name__ == ‘__main__‘:
        print(config.param)  # 200

可以看到,原param的值是100,在inner_method中对其进行了修改,由于导入的config,所以修改的是原module中的值,在另外一个文件中导入的再导入该module时打印的是修改后的值,如果换一种导入方式情况就不同了:

  1. # config.py
    param = 100
  1. # inner_method.py
    from config import param
    param = 200
  1. # outer_method.py
    import inner_method as inter
    from config import param

    if __name__ == ‘__main__‘:
        print(param)  # 100

这种修该并不会反映到config这个module里,因为param已经被导入到inner_method的命名空间,所以这边打印的值仍然是param的原值,明白这个原理,有时候可以避免一些代码错误。

对上面的简介做个总结,即import导入的模块会保留自己的命名空间,这就是为什么你需要使用模块名来访问它的函数或属性(module.function)的原因。而from module import则要从另一个模块中将指定的函数和属性导入到你自己的名字空间,这就是为什么你可以直接访问它们却不需要引用它们所来源的模块的原因。

说到这里,又出现一个新问题,为什么我们可以直接使用str(),dict()等函数,而不需要显示的导入他们呢,下面就介绍下这个。

三、__builtin__

python是按LEGB原则来查找函数,变量等的,即L-Local(function):函数内的名字空间;E-Enclosing function locals:外部嵌套函数的名字空间(例如closure);G-Global(module):函数定义所在模块(文件)的名字空间;B-Builtin(Python):Python内置模块的名字空间。所以在本文件内找不到的参数或者函数就会到内建模块中寻找。

在Python2.X版本中,内建模块被命名为__builtin__,当使用内建模块中函数或其它功能时,可以直接使用,不用添加内建模块的名字;但是,如果想要向内建模块中添加一些功能,以便在任何函数中都能直接使用而不 用再进行import,这时,就要导入内建模块,在内建模块的命名空间(即__dict__字典属性)中添加该功能,例如:

  1. # inner_method.py
  1. import __builtin__

    def add_func(a,b):
        return 100*a + 10*b
    __builtin__.__dict__[‘add_test‘] = add_func

    if __name__ == ‘__main__‘:
        print add_test(1, 2)  # 120

由上面的代码看出,add_test已经加到了内建空间,可以直接对其进行使用了。

还有一个__builtins__,那这个是什么呢?其实它是对内建模块一个引用,在程序启动时他会随着内建模块一起被加载入内存,和__builtin__不同,在任何模块不需导入都可以看到__builtins__,但是在__main__中__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__,在非__main__模块中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身,先看个例子:

  1. # inner_method.py
  1. import __builtin__

    def add_func(a,b):
        return 100*a + 10*b
    __builtin__.__dict__[‘add_test‘] = add_func

    if __builtin__ is __builtins__:
        print(‘in main, __builtin__ is __builtins__‘)
        print(type(__builtins__))
        print (__builtins__)
    if __builtin__.__dict__ is __builtins__:
        print(‘not in main, __builtin__.__dict__ is __builtins__‘)
        print(type(__builtins__))
        print dir(__builtin__.__dict__)

    if __name__ == ‘__main__‘:
        print add_test(1, 2)

在inner_method文件里执行,得到的结果是这样的:

in main, __builtin__ is __builtins__

<type ‘module‘>

<module ‘__builtin__‘ (built-in)>

120

说明在__main__中执行__builtin__就是__builtins__,它的type是一个module,如果我们在outer_method中导入再执行,例子如下:

  1. # outer_method.py
  1. import inner_method

    if __name__ == ‘__main__‘:
        print add_test(1, 2)

结果是这样的:

not in main, __builtin__.__dict__ is __builtins__

<type ‘dict‘>

[‘__class__‘, ‘__cmp__‘, ‘__contains__‘, ‘__delattr__‘, ‘__delitem__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__getitem__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__iter__‘, ‘__le__‘, ‘__len__‘, ‘__lt__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__setitem__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘clear‘, ‘copy‘, ‘fromkeys‘, ‘get‘, ‘has_key‘, ‘items‘, ‘iteritems‘, ‘iterkeys‘, ‘itervalues‘, ‘keys‘, ‘pop‘, ‘popitem‘, ‘setdefault‘, ‘update‘, ‘values‘, ‘viewitems‘, ‘viewkeys‘, ‘viewvalues‘]

120

说明在导入的情况下执行__builtins__是__builtin__.__dict__,他是一个字典,正是由于这种特性,所以在使用的时候推荐直接使用__builtin__,因为可控的总是比不可控的要更好,在大多数地方,都是使用__builtin__为内建模块添加信息。

从__name__=='__main__'说到__builtin__

原文地址:https://www.cnblogs.com/small-office/p/9337669.html

时间: 2024-08-30 09:48:20

从__name__=='__main__'说到__builtin__的相关文章

python中if __name__ == &#39;__main__&#39;:

Using a module's __name__ Example? 8.2.? Using a module's __name__ #!/usr/bin/python # Filename: using_name.py if __name__ == '__main__': print 'This program is being run by itself' else: print 'I am being imported from another module' Output $ pytho

python &#160; __name__==&#39;__main__&#39; 用法

python 文件的后缀为.py,比如 name.py python 文件可以直接执行,也可以被导入.调用,比如import name; script 1: #!/bin/python # Filename:name.py if __name__=='__main__':     print 'This program is being run by itself' else:     print 'I am being imported from another module' script

if __name__ == &#39;__main__&#39; 如何正确理解

今天刷知乎,突然看到这个问题,发现很多人都是简单的回答了一下,对于很多人来说,更准确的说应该是大部分的 Python 初学者,这样的回答很容易让人理解.所以这里我来做说一下,希望能把这个问题说明白. 先举一个例子:假设我们有一个add.py文件,里面的代码是这样: def add(a, b):    return a + badd(1,2)#用于测试上面函数是否正常 这里就是一个求两数之和的函数,然后我在另一个文件中调用这个模块,这个时候就会把add(1,2)也运行,但是我是不希望运行add(1

【Python中if __name__ == &#39;__main__&#39;: 的解析】

在很多Python代码中,在代码的最下方会看到  if __name__ == '__main__':,这段代码到底有什么用呢? 在理解这个语句的作用前,需要知道的是,一般的Python文件后缀为.py,其可以拿来执行,也可以用来作为模块使用import导入.当Python解析器读取一个源文件时它会执行所有的代码.在执行代码前会定义一些特殊的变量.如果解析器运行的模块(源文件)作为主程序,它将会把__name__变量设置成"__main__".如果只是引入其他的模块,__name__变

python unittest不执行&quot;if __name__ == &#39;__main__&#39; &quot;问题

问题: selenium导入unittest框架和HtmlReport框架后,HtmlReport不被执行. 假设代码为: from selenium import webdriver import unittest class Test(unittest.TestCase): print "this is class Test" def setup(self): print "this is setup" def test_1(self): print "

扫盲贴000---关于python中的if __name__ == &#39;__main__&#39;

对于python中的__name__变量,根据调用python文件的方式不同,__name__变量的值也会不同.假如我有一个名为hello_world.py的python脚本,当我的目的是直接运行这个文件"python hello_world.py"的时候,这个时候对于hello_world.py的__name__变量的值为"__main__".但是当我们把hello_world.py作为一个模块被另一个模块引入的时候"import hello_world

python中if __name__==&rsquo;__main__&rsquo;的作用

意思是如果该.py文件是自己执行则__name__被赋值为__main__,否则赋值为文件名. 作用: 有句话经典的概括了这段代码的意义: "Make a script both importable and executable" 意思就是说让你写的脚本模块既可以导入到别的模块中用,另外该模块自己也可执行. 举例: 先写一个模块: #module.py def main(): print "we are in %s"%__name__ if __name__ ==

python之if __name__ == &#39;__main__&#39;

概要: 之前一直在写shell最近在学习python,在学习中看到书上举例的代码有这样一行: if __name__ == '__main__' 百度看了很多解释也没彻底弄懂,自己又继续研究最后总结一下,如有不对的地方请根正不胜感激. 网上的解释很多都是说这句代码的含义是为了调用.说的对,但是不全,为了更好的理解我写了两个脚本进行测试(这里我直接在虚拟机上编写了学习的时候还是建议使用Python的IDE来提高我们的效率) 脚本1: [[email protected] tmp]# cat nam

python中if __name__ == &#39;__main__&#39;: 的解析

当你打开一个.py文件时,经常会在代码的最下面看到if __name__ == '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且所有的模块都有一个内置属性 __name__.一个模块的 __name__ 的值取决于您如何应用模块.如果 import 一个模块,那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名.但是您也可以像一个标准的程序样直接运行模块,在这 种情况下, __name__ 的值将是一个特别缺省"__main__". //////