一、__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. 032:DTL常用过滤器(1)

    为什么需要过滤器: 在DTL中,不支持函数的调用形式‘()’,因此不能给函数传递参数,这将有很大的局限性:而过滤器其实就是一个函数,可以对需要处理的参数进行处理,并且还可以额外接受一个参数(也就是说: ...

  2. 【leetcode】1035. Uncrossed Lines

    题目如下: We write the integers of A and B (in the order they are given) on two separate horizontal line ...

  3. git本地创建一个分支并上传到远程服务器上

    git branch 查看分支 新建分支:git checkout -b dev 把新建的本地分支push到远程服务器 git push origin 本地名字:外地名字 删除远程分支 git pus ...

  4. vue服务器端渲染指南研究

    什么是服务器端渲染(SSR)? Vue.js 是构建客户端应用程序的框架.默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM.然而,也可以将同一个组件渲染为服务器端的 HT ...

  5. handy源码阅读(一):EventBase类

    类EventBase继承于类EventBases,继承于noncopyable.  其中noncopyable是一个去除了拷贝构造和赋值构造的类. noncopyable: class noncopy ...

  6. Jmeter参数化控件意见收集

    1.可以读取EXCEL,可以自定义SHEET,行和列: 2.数据可以加密传输,加密方式如下: 1)SHA1 2)SHA224 3)SHA256 4)SHA384 5)SHA512 6)MD5 7)Hm ...

  7. 历时小半年总结之JAVA

    一.JavaSE 1.多线程 (1).进程与线程的区别? 答:进程是所有线程的集合,每一个线程是进程中的一条执行路径,线程只是一条执行路径. (2).为什么要用多线程? 答:提高程序效率 (3).多线 ...

  8. CentOS 7.5 通过kubeadm部署k8s-1.15.0

    kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,伴随Kubernetes每个版本的发布都会同步更新,kubeadm会对集群配置方面的一些实践做调整,通过实验k ...

  9. UNITY崩溃的日志

    有关UNITY的日志,有两个路径. 1,一般日志路径:C:/Users/xxxx/ AppData/Local/Unity/Editor,此文件夹下有三个文件 ,如下图:Editor.log, Edi ...

  10. IQueryable不能使用异步方法的解决方案

    ---恢复内容开始--- 看见别人用Linq to Sql的Async好久了,我还没开始用,感觉太土了,跟不上潮流了,打开vs,就准备写个查询,然后发现我用一个IQueryable的对象,怎么都点不出 ...