从Python的两种导入模块(from import和import)方式谈命名空间与作用域
2018-02-07 15:43
666 查看
在谈论python命名空间之前,首先介绍一个因为python命名空间引起的坑。
一、问题实例
项目中使用pyqt编写gui,gui在处理文本文件时使用了10进制转16进制的hex函数
代码片段:
from PyQt4.QtCore import *
print hex(10)期望的输出为0xa,但实际上运行的时候报错
TypeError: hex(QTextStream): argument 1 has unexpected type 'int' 检查了后发现了是PyQt4.QtCore中存在hex函数,导致系统函数hex被重载了。这个问题是python命名空间
与作用域导致的,那么,什么是python的命名空间与作用域呢?
二、命名空间(Namespace)
【定义】
名称到对象的映射。命名空间由一个字典实现,键为变量名,值是变量对应的值。各个命名空间是独立的,
一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响。
【分类】
Python程序执行期间会有2个或3个活动的命名空间(函数调用时有3个,函数调用结束后2个)。按照
变量定义的位置,可以划分为以下3类:
1 、Local。局部命名空间,每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、
内部定义的局部变量。
local命名空间可以在函数中使用locals()函数获取。def test_function_namespace():
a = 1
b = 2
print locals()执行结果如下,表示a,b两个变量属于test_function_namespace这个函数的本地命名空间:{'a': 1, 'b': 2}
2、Global。全局命名空间,每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、
类、其他导入的模块、模块级的变量与常量。
global命名空间可以在模块中任意位置使用globals()函数获取。def test_module_namespace():
a = 1
b = 2
print globals() 执行结果如下,可以看到test_module_namespace中的
4000
a、b变量并不属于该模块的全局命名空间,说明
local与global命名空间是相互隔离的:{'test_class_namespace': <function test_class_namespace at 0x02ABFDF0>, 'test_module_namespace': <function test_module_namespace at 0x02ABFDB0>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'Z:/test/test_celery/tasks/test.py', 'TestClass': <class '__main__.TestClass'>, '__package__': None, 'test_instance_namespace': <function test_instance_namespace at 0x02ABFEF0>, 'test_function_namespace': <function test_function_namespace at 0x02A7AAB0>, '__name__': '__main__', '__doc__': None}
3、Built-in,python自带的内建命名空间,任何模块均可以访问,放着内置的函数和异常。从某种意义上来
说,一个对象(object)或类(Class)的所有属性(attribute)(包含方法)也构成了一个namespace。在程序执行
期间,有多个类实例就会有多个命名空间同时存在。
类或对象的命名空间用__dict__()方法获取获取类的命名空间
{'a': 1, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'TestClass' objects>, '__weakref__': <attribute '__weakref__' of 'TestClass' objects>, '__doc__': None, '__init__': <function __init__ at 0x0299FFB0>}期望的输出为0xa,但实际上运行的时候报错
获取对象的命名空间
def test_instance_namespace():
test_instance = TestClass()
print test_instance.__dict__ 执行结果如下,每一个实例都会有一个独立的命名空间:
{'b': 2}
三、作用域(Scope)
【定义】
作用域是针对变量而言,指申明的变量在程序里的可应用范围。或者称为变量的可见性。
【分类】
Local(函数内部)局部作用域
Enclosing(嵌套函数的外层函数内部)嵌套作用域(闭包)
Global(模块全局)全局作用域
Built-in(内建)内建作用域
【变量查找法则】
当程序引用某个变量的名字时,就会从当前名字空间开始搜索。搜索顺序规则便是: LEGB。即从内往外一层
一层的查找,找到了之后,便停止搜索,如果最后没有找到,则抛出在NameError的异常
【命名空间与作用域的关系】
命名空间定义了在某个作用域内变量名和绑定值之间的对应关系,命名空间是键值对的集合,变量名与值是
一一对应关系。作用域定义了命名空间中的变量能够在多大范围内起作用。
四、解决方案:
在module_yy中执行from module_xx import func_xx后,module_yy的命名空间中就拥有了func_xx。
后面再更改module_xx 命名空间中的fun_xx,不会改变module_yy的命名空间中的func_xx。
而在module_yy中执行import module_xx 后,module_yy的命名空间中就拥有了module_xx。可以通过
module_xx.func_xx调用函数,后面再更改module_xx 命名空间中的fun_xx,在module_yy的调用
module_xx.func_xx也会改变。
修改后的代码:import PyQt4.QtCore
print hex(10)输出为:0xa
五、疑问:
为何大部分python源代码都使用了from module_xx import func_xx方式?
一、问题实例
项目中使用pyqt编写gui,gui在处理文本文件时使用了10进制转16进制的hex函数
代码片段:
from PyQt4.QtCore import *
print hex(10)期望的输出为0xa,但实际上运行的时候报错
TypeError: hex(QTextStream): argument 1 has unexpected type 'int' 检查了后发现了是PyQt4.QtCore中存在hex函数,导致系统函数hex被重载了。这个问题是python命名空间
与作用域导致的,那么,什么是python的命名空间与作用域呢?
二、命名空间(Namespace)
【定义】
名称到对象的映射。命名空间由一个字典实现,键为变量名,值是变量对应的值。各个命名空间是独立的,
一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响。
【分类】
Python程序执行期间会有2个或3个活动的命名空间(函数调用时有3个,函数调用结束后2个)。按照
变量定义的位置,可以划分为以下3类:
1 、Local。局部命名空间,每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、
内部定义的局部变量。
local命名空间可以在函数中使用locals()函数获取。def test_function_namespace():
a = 1
b = 2
print locals()执行结果如下,表示a,b两个变量属于test_function_namespace这个函数的本地命名空间:{'a': 1, 'b': 2}
2、Global。全局命名空间,每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、
类、其他导入的模块、模块级的变量与常量。
global命名空间可以在模块中任意位置使用globals()函数获取。def test_module_namespace():
a = 1
b = 2
print globals() 执行结果如下,可以看到test_module_namespace中的
4000
a、b变量并不属于该模块的全局命名空间,说明
local与global命名空间是相互隔离的:{'test_class_namespace': <function test_class_namespace at 0x02ABFDF0>, 'test_module_namespace': <function test_module_namespace at 0x02ABFDB0>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'Z:/test/test_celery/tasks/test.py', 'TestClass': <class '__main__.TestClass'>, '__package__': None, 'test_instance_namespace': <function test_instance_namespace at 0x02ABFEF0>, 'test_function_namespace': <function test_function_namespace at 0x02A7AAB0>, '__name__': '__main__', '__doc__': None}
3、Built-in,python自带的内建命名空间,任何模块均可以访问,放着内置的函数和异常。从某种意义上来
说,一个对象(object)或类(Class)的所有属性(attribute)(包含方法)也构成了一个namespace。在程序执行
期间,有多个类实例就会有多个命名空间同时存在。
类或对象的命名空间用__dict__()方法获取获取类的命名空间
def test_class_namespace(): print TestClass.__dict__执行结果如下,所有TestClass类的对象共享该命名空间:
{'a': 1, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'TestClass' objects>, '__weakref__': <attribute '__weakref__' of 'TestClass' objects>, '__doc__': None, '__init__': <function __init__ at 0x0299FFB0>}期望的输出为0xa,但实际上运行的时候报错
获取对象的命名空间
def test_instance_namespace():
test_instance = TestClass()
print test_instance.__dict__ 执行结果如下,每一个实例都会有一个独立的命名空间:
{'b': 2}
三、作用域(Scope)
【定义】
作用域是针对变量而言,指申明的变量在程序里的可应用范围。或者称为变量的可见性。
【分类】
Local(函数内部)局部作用域
Enclosing(嵌套函数的外层函数内部)嵌套作用域(闭包)
Global(模块全局)全局作用域
Built-in(内建)内建作用域
【变量查找法则】
当程序引用某个变量的名字时,就会从当前名字空间开始搜索。搜索顺序规则便是: LEGB。即从内往外一层
一层的查找,找到了之后,便停止搜索,如果最后没有找到,则抛出在NameError的异常
【命名空间与作用域的关系】
命名空间定义了在某个作用域内变量名和绑定值之间的对应关系,命名空间是键值对的集合,变量名与值是
一一对应关系。作用域定义了命名空间中的变量能够在多大范围内起作用。
四、解决方案:
在module_yy中执行from module_xx import func_xx后,module_yy的命名空间中就拥有了func_xx。
后面再更改module_xx 命名空间中的fun_xx,不会改变module_yy的命名空间中的func_xx。
而在module_yy中执行import module_xx 后,module_yy的命名空间中就拥有了module_xx。可以通过
module_xx.func_xx调用函数,后面再更改module_xx 命名空间中的fun_xx,在module_yy的调用
module_xx.func_xx也会改变。
修改后的代码:import PyQt4.QtCore
print hex(10)输出为:0xa
五、疑问:
为何大部分python源代码都使用了from module_xx import func_xx方式?
相关文章推荐
- Python 中 一个模块文件导入操作:import 和 from ,以及reload调用
- python中模块导入语句 from ..import ..与from import as的区别
- 在python用import或者from...import来导入相应的模块
- python import 和 from.........import 模块加载和作用域
- from ....import导入其他路径的模块 分类: python基础学习 2013-10-11 15:13 315人阅读 评论(0) 收藏
- Python 实现抽象类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)
- Python导入模块(包)的两种方式 TypeError: 'module' object is not callable
- Python的一个命名空间冲突,关于from-import机制
- python模块的导入的两种方式区别详解
- python导入模块的两种方式
- python中的命名空间和作用域
- python编程_python通过get方式,post方式发送http请求和接收http响应_import urllib模块,import urllib2模块,import httplib模块
- 关于python 中的__future__模块(from __future__ import ***)
- Python基础-作用域和命名空间(Scope and Namespace)
- python基础-模块import几种方式、__name__使用、__all__使用、模块搜索路径、
- python分层目录导入另外目录的模块 import
- Python的命名空间和作用域
- python的命名空间和作用域
- Python3导入自定义模块的3种方式
- 菜鸟学Python Day1.4(导入模块Import、用户交互Raw_input)