从__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__ 的值通常为 ...
随机推荐
- RMQ Terminology
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11784644.html RMQ模型架构 RMQ Terminology Message 消息,消息是不 ...
- Selenium-ActionChainsApi介绍
ActionChains 模拟鼠标悬浮到某一个位置,做一系列的连贯操作,使用Selenium提供的ActionChains模块 引入方式 from selenium.webdriver.common. ...
- 4412 使用usb摄像头拍照YUYV格式
一.内核设置 Linux内核中已经带有很完善的USB摄像头驱动,支持几乎所有的USB摄像头,我们只需要配置内核,选择上相应的Sensor型号即可. 配置内核,支持USB摄像头: Device Driv ...
- 【テンプレート】LCA
LCA目前比较流行的算法主要有tarjian,倍增和树链剖分 1)tarjian 是一种离线算法,需要提前知道所有询问对 算法如下 1.读入所有询问对(u,v),并建好树(建议邻接表) 2.初始化每个 ...
- NOIp 数据结构专题总结 (1):STL、堆、并查集、ST表、Hash表
系列索引: NOIp 数据结构专题总结 (1) NOIp 数据结构专题总结 (2) STL structure STL 在 OI 中的运用:https://oi.men.ci/stl-in-oi/ s ...
- [CSP-S模拟测试]:数字(数学+高精度)
题目描述 很简单,给出正整数$n$,求出$n!$在十进制表示下的从最末非零位开始的总共$k$位. 输入格式 第一行一个正整数$T$,表示有$T$组数据接下来$T$行,每行两个正整数$n$和$k$. 输 ...
- LintCode之移动零
题目描述: 分析:由于要使非零元素保持原数组的顺序,我只能想出在找到一个0时,逐个移动数组元素使得后一个元素覆盖前一个元素,再将这个0移到后头去. 我的代码: public class Solutio ...
- inline-block的间隙问题 box-orient属性 line-clamp属性 margin问题
只要设了 display:inline-block 将元素变成行级块元素的时候,会自带空隙,即使你设了 margin 和 padding 依然没有效果! 解决办法:只要在父元素上加上font-size ...
- ubuntu18.04英文环境解决各种软件中文乱码问题
如果要同时支持中文也支持英文,进入到该软件的字体设置界面,字体格式选择为: Noto Sans CJK SC
- PHP之导出CSV文件
序言 Q1:什么是csv文件? A1:csv即 comma-separated values ,逗号分隔值.是一种通用的相对简单地文件格式,目前被较为广泛的使用.其最广泛的应用就是用来转移表数据. “ ...