一、__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__的更多相关文章

  1. if __name__== "__main__" 的意思(作用)python代码复用

    if __name__== "__main__" 的意思(作用)python代码复用 转自:大步's Blog  http://www.dabu.info/if-__-name__ ...

  2. Python中的if __name__='__main__'语句的作用

    笔者在自学Python的过程中,对于if __name__='__main__'的用法感到很困惑,在think Python一书中原作者的源代码是这么解释if __name__='__main__'语 ...

  3. 【Python】if __name__ == "__main__"做了什么?

    在Python的很多源文件中,会有这样的语句: if __name__ == '__main__': # script code here 比如有两个源文件A.py和B.py,都有上面的代码:在B.p ...

  4. 浅析python 中__name__ = '__main__' 的作用

    引用http://www.jb51.net/article/51892.htm 很多新手刚开始学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码 ...

  5. python中if __name__ == '__main__': 的解析

    当你打开一个.py文件时,经常会在代码的最下面看到if __name__ ==  '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且所有的模块都有一个内置属性 __name__.一 ...

  6. python 中__name__ = '__main__' 的作用

    有句话经典的概括了这段代码的意义: "Make a script both importable and executable" 意思就是说让你写的脚本模块既可以导入到别的模块中用 ...

  7. python中if __name__ == "__main__":用法解析

    __name__: __name__作为模块的内置属性,简单点说呢,就是.py文件的调用方式. __main__: 如果__name__等于"__main__"就表示是直接执行. ...

  8. if __name__ == '__main__':

    python if __name__ == '__main__': 模块是对象,并且所有的模块都有一个内置属性 __name__.一个模块的 __name__ 的值取决于您如何应用模块.如果 impo ...

  9. python if __name__ == '__main__'解析

    废话不多说,正题: python中所有的模块都有一个内置属性 __name__,一个模块的 __name__ 的值取决于如何应用模块.如果 import 一个模块,那么模块__name__ 的值通常为 ...

随机推荐

  1. MyCAT操作MySQL示例之E-R表

    接着上一篇继续..... E-R 关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,即子表依赖于父表,通过表分组(Table Group)保证数据 Join 不会跨库操作. 表分 ...

  2. C++指针的指针和指针的引用

    https://www.cnblogs.com/li-peng/p/4116349.html

  3. char* 和 cha[]

    char* s1 = "hello";//字符串常量 s是一个保存了字符串首地址的指针变量,同时也是字符串的名字,s的内容是第一个字符的地址,当s指向常量字符串时候,内容不能改变( ...

  4. 【Unity优化】Unity中究竟能不能使用foreach?

    关于这个话题,网络上讨论的很多,我也收集了一些资料,都不是很齐全,所以自己亲自测试,这里把结果分享给大家. foreach究竟怎么了? 研究过这个问题的人都应该知道,就是它会引起频繁的GC Alloc ...

  5. Advanced search keywords

    Advanced search options Find what you're looking for in less time. Use the following symbols to quic ...

  6. 测开之路七十七:shell之if、case、for、while

    选择语句(if语句) 大于:-gt判断目录是否存在:-d if [ 判断条件 ]; then statement1 Statement2elif [ 判断条件 ]; then statement1 S ...

  7. POJ - 3176 Cow Bowling 动态规划

    动态规划:多阶段决策问题,每步求解的问题是后面阶段问题求解的子问题,每步决策将依赖于以前步骤的决策结果.(可以用于组合优化问题) 优化原则:一个最优决策序列的任何子序列本身一定是相当于子序列初始和结束 ...

  8. EasyUI在子tab基础上再打开新的tab标签页

    var title = "xxxx"; var content = '<iframe scrolling="auto" frameborder=" ...

  9. idea 快捷键汇总

    1.IDEA常用快捷键 Alt+回车 导入包,自动修正 Ctrl+N 查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导入的类和包 Alt+In ...

  10. CPU高速缓存行与内存关系 及并发MESI 协议(转载)

    原文链接 http://www.cnblogs.com/jokerjason/p/9584402.html 先来一个整体图 一. 大致关系: CPU Cache --> 前端总线 FSB (下图 ...