从__name__=='__main__'说到__builtin__
一、__name__
我们在写好代码进行自测的时候一般会先写这样一行代码:
# inter_method
if __name__ == '__main__':
为什么呢,可能并不是所有人都考虑过,这个就类似与C语言中的main一样,是一个函数的入口,python写的各个module都可以包含这样一个入口,但是在本module执行的时候,__name__就是__main__,而被导入的时候__name__就是module的名称,所以上面那行代码可以保证我们的测试代码只在本module生效而在被导入时并不执行,先看下面的代码print出的值就是__main__。
# inter_method
- def inter():
print(__name__)if __name__ == '__main__':
inter() # __main__
如果被引用呢,我们从外部模块导入inter方法,看下面的代码:
# outer_method
- import inner_method
if __name__ == '__main__':
print __name__ # __main__
inner_method.inter() # inner_method
原文件打印的就不再是__main__了,所以测试代码不会执行。
有人会说,我导入时候不是就已经知道模块名了吗,为什么还要通过__name__来获取,其实有时候我们不一定知道,比如我们在中间导入的时候把模块名as成了其他名称,另一个模块再从这里导入我们就不知道原始的模块名了,比如:
# outer_method
- import inner_method as inter
# another
- from outer_method import inter
if __name__ == '__main__':
print __name__ # __main__
print inter.__name__ # inner_method
在这种情况下,在another中我们不知道原始模块名的,但是__name__确是知道的。
__name__在模块中是代表module名,在类中代表类名,在方法中代表方法名,看下面的代码:
# inter_method
- 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
- 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的一部分。我们看个例子:
- # config.py
param = 100
- # inner_method.py
import config
config.param = 200
- # outer_method.py
import inner_method as inter
import configif __name__ == '__main__':
print(config.param) # 200
可以看到,原param的值是100,在inner_method中对其进行了修改,由于导入的config,所以修改的是原module中的值,在另外一个文件中导入的再导入该module时打印的是修改后的值,如果换一种导入方式情况就不同了:
- # config.py
param = 100
- # inner_method.py
from config import param
param = 200
- # outer_method.py
import inner_method as inter
from config import paramif __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__字典属性)中添加该功能,例如:
- # inner_method.py
- import __builtin__
def add_func(a,b):
return 100*a + 10*b
__builtin__.__dict__['add_test'] = add_funcif __name__ == '__main__':
print add_test(1, 2) # 120
由上面的代码看出,add_test已经加到了内建空间,可以直接对其进行使用了。
还有一个__builtins__,那这个是什么呢?其实它是对内建模块一个引用,在程序启动时他会随着内建模块一起被加载入内存,和__builtin__不同,在任何模块不需导入都可以看到__builtins__,但是在__main__中__builtins__是对内建模块__builtin__本身的引用,即__builtins__完全等价于__builtin__,在非__main__模块中,__builtins__仅是对__builtin__.__dict__的引用,而非__builtin__本身,先看个例子:
- # inner_method.py
- import __builtin__
def add_func(a,b):
return 100*a + 10*b
__builtin__.__dict__['add_test'] = add_funcif __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中导入再执行,例子如下:
- # outer_method.py
- 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__的更多相关文章
- if __name__== "__main__" 的意思(作用)python代码复用
if __name__== "__main__" 的意思(作用)python代码复用 转自:大步's Blog http://www.dabu.info/if-__-name__ ...
- Python中的if __name__='__main__'语句的作用
笔者在自学Python的过程中,对于if __name__='__main__'的用法感到很困惑,在think Python一书中原作者的源代码是这么解释if __name__='__main__'语 ...
- 【Python】if __name__ == "__main__"做了什么?
在Python的很多源文件中,会有这样的语句: if __name__ == '__main__': # script code here 比如有两个源文件A.py和B.py,都有上面的代码:在B.p ...
- 浅析python 中__name__ = '__main__' 的作用
引用http://www.jb51.net/article/51892.htm 很多新手刚开始学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码 ...
- python中if __name__ == '__main__': 的解析
当你打开一个.py文件时,经常会在代码的最下面看到if __name__ == '__main__':,现在就来介 绍一下它的作用. 模块是对象,并且所有的模块都有一个内置属性 __name__.一 ...
- python 中__name__ = '__main__' 的作用
有句话经典的概括了这段代码的意义: "Make a script both importable and executable" 意思就是说让你写的脚本模块既可以导入到别的模块中用 ...
- python中if __name__ == "__main__":用法解析
__name__: __name__作为模块的内置属性,简单点说呢,就是.py文件的调用方式. __main__: 如果__name__等于"__main__"就表示是直接执行. ...
- if __name__ == '__main__':
python if __name__ == '__main__': 模块是对象,并且所有的模块都有一个内置属性 __name__.一个模块的 __name__ 的值取决于您如何应用模块.如果 impo ...
- python if __name__ == '__main__'解析
废话不多说,正题: python中所有的模块都有一个内置属性 __name__,一个模块的 __name__ 的值取决于如何应用模块.如果 import 一个模块,那么模块__name__ 的值通常为 ...
随机推荐
- Flsak中的socket是基于werkzeug实现的。
from werkzeug.serving import run_simple from werkzeug.wrappers import Request,Respinse @Request.appl ...
- 继续写高精!noip2012国王游戏。。。
国王游戏 题目描述: 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王 ...
- 20180709-Java循环结构
while(布尔表达式){ //循环内容} public class Test{ public static void main(String args[]){ int x = 10; while(x ...
- womenzijide
<!DOCTYPE html><html lang="en"> <head> <meta http-equiv="Content ...
- RHEL7(RedHat 7)本地yum源的配置
配置yum 源 1.挂载DVD光盘到/mnt 因为配置时候路径名里面不能有空格,否则不能识别 [root@ mnt]# mount /dev/cdrom /mnt 2.在目录/etc/yum.r ...
- Hive presto和hive时间格式转换
1.北京时间格式 to unix时间格式 数据格式: 2017-11-17 08:28:13 2017-11-17 08:28:10 2017-11-17 08:27:51.343 2017- ...
- 制作自己的win7系统
每次安装完纯净版的系统,然后是漫长的打补丁,装驱动,装软件.不妨制作一个自己的系统光盘(也就是GHOST系统),再要重装系统时,直接用这个系统光盘,一键安装,方便省时. 制作GHOST系统,就是将本地 ...
- 【大前端攻城狮之路·二】Javascript&QA⼯程师
今天给大家分享的主题的是Javascript&QA⼯程师.看到这个主题,可能有人问:前端开发完就OK了,剩下的丢给测试就行,哪里还需要关心这些?但事实上呢,测试是前端开发非常重要的环节,也是迈 ...
- apicloud地图、即时通讯、人脸识别登录、以及平时踩过得坑
apicloud技术浅谈 导语 apicloud 的学习也有一段时间了,这是我个人的一些经验,和踩过的坑,希望对大家能有一些帮助. apicloud的知识准备 apicloud 是一个用原生的思想搭建 ...
- Vagrant 手册之同步目录 - 基本用法
原文地址 - 概述 原文地址 - 基本用法 同步目录 Synced folder 支持在宿主机和客户机之间共享目录,从而允许你在宿主机的项目文件上工作,但是可以在客户机上编译并运行. 默认情况下,Va ...