python引用问题

1. 绝对引用,相对引用(absolute_import and relative import)
package/__init__.py
pachage/lala.py
pachage/sys.py

假设在lala.py中import sys,是引用的当前目录的sys, 还是标准库里的sys?来看一下

lala.py

import sys
print str(sys)

sys.py, __init__.py都是空文件即可

看一下执行结果

bogon:package licong$ python -m package.lala
<module ‘package.sys‘ from ‘package/sys.pyc‘>

可以知道,python是按照sys.path的优先级去寻找的模块,如果找到就停止加载,而sys.path排在第一个的就是当前目录,所以这就是所谓的隐式的相对引用。

好在python2.5中我们后提供了一种修改这种行为的方法,来看一下

lala.py修改为

from __future__ import absolute_import
import sys
print str(sys)

来看一下结果

bogon:package licong$ python -m package.lala
<module ‘sys‘ (built-in)>

区别只是添加了from __future__ import absolute_import这句话

如果我们想用当前目录的sys模块怎么办?可以通过显示的相对引用来解决。

lala.py修改为

from __future__ import absolute_import
import sys
from . import sys as haha
print str(sys)
print str(haha)
bogon:package licong$ python -m package.lala
<module ‘sys‘ (built-in)>
<module ‘package.sys‘ from ‘package/sys.pyc‘>

总结一下包中的几种引用方法,还是以例子中的文件结构举例

import package.sys 绝对引用
import package.sys 绝对引用且绑定别名
from package import sys 可替代的绝对引用
import sys 隐式的相对引用 
from . import sys 显示的相对引用

2. 循环导入问题

c1.py

from c2 import g
def x():
    pass

c2.py

from c1 import x
def g():
    pass

上面这两个文件执行任何一个文件都会报错,原因拿c1.py举例

1.执行c1,
2.c1第一行需要引用c2中的g,执行c2
3.c2第一行引用c1中的x,执行c1
4.由于c1并没有执行完成,x并不存在
5.报错

再举一个更好的例子

a.py:

print "a in"
import sys
print "b imported: %s" % ("b" in sys.modules, )
import b
print "a out"

b.py:

print "b in"
import a
print "b out"
x = 3

执行a.py

$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
b out
a out

如果在a.py中添加
print b.x

则会报错

原因是, x只有在b out后才会存在,而a out后就会执行print b.x,而a out 是在b out 之前的。

解决方法:
1 延迟import

c1.py

from c2 import g
def x():
    return g()
print x()

c2.py

def g():
    return 123
from c1 import x

但是,这样修改的前提是g函数不会依赖c1

2. import到写到函数内部

c1.py

def x():
    from c2 import g
    return g()
print x()

c2.py

def g():
    from c1 import x
    return 123

这样只有函数执行时,才会加载响应模块,但是如果有多个函数依赖其他模块,就需要写多遍,非常蠢。

3. 包
首先要明确,如果不是在包中,是不该出现相对引用这种情况的。
如果是在包中,上面这个问题是有解决方法的(因为包是一个整体,包的每个组件单独执行没有任何意义,而非包每个文件是可以独立执行的)

假设包结构是
package/__init__.py
package/a.py
package/b.py

解决方案1 
使用import而不要使用from import

a.py

import package.b
def x():
    pass
def haha():
    print package.b.g()

b.py

import package.a
def g():
    return 123

可以看到,成功了

>>> import package.a
>>> package.a
<module ‘package.a‘ from ‘package/a.pyc‘>
>>> package.a.haha()
123
>>> 

解决方案2
把from import 写到__init__.py中
__init__.py

from . import a, b

a.py

import package
def x():
    pass

def haha():
    print package.b.g()

b.py

import package
def g():
    return 123

结果是一样的

时间: 2024-08-04 04:50:11

python引用问题的相关文章

Python引用复制,参数传递,弱引用与垃圾回收

引用 先上个示例: >>> val = [1] >>> val[0] = val >>> val [[...]] 上述代码使val中包含自身,而产生了无限递归.上述示例表明Python中的变量名为引用类型,赋值只是使得左值指向与右值相同的内存对象. is运算符可以判断两个引用是否指向了同一个对象,而==运算符判断两个引用指向的值是否相等而不关心指向什么对象. 对引用不了解的朋友,可以把Python引用与C/C++中的void *类比,不过因为垃圾回收机

Python引用模块和查找模块路径

模块间相互独立相互引用是任何一种编程语言的基础能力.对于"模块"这个词在各种编程语言中或许是不同的,但我们可以简单认为一个程序文件是一个模块,文件里包含了类或者方法的定义.对于编译型的语言,比如C#中的一个.cs文件,Java中的一个.java或者编译后的.class文件可以认为是一个模块(但常常不表述为模块):对于解释型的语言会更加直观些,比如PHP的.php文件,在Python中就是.py文件可以认为是一个模块.在"模块"之上有"包",主要是

Python入门之Python引用模块和查找模块路径

#这篇文章主要介绍了Python引用模块和Python查找模块路径的相关资料,需要的朋友可以参考下 模块间相互独立相互引用是任何一种编程语言的基础能力.对于"模块"这个词在各种编程语言中或许是不同的,但我们可以简单认为一个程序文件是一个模块,文件里包含了类或者方法的定义.对于编译型的语言,比如C#中的一个.cs文件,Java中的一个.java或者编译后的.class文件可以认为是一个模块(但常常不表述为模块):对于解释型的语言会更加直观些,比如PHP的.php文件,在Python中就是

Python 引用

python引用python中的数值类型变量也是引用,例如: a = 100b=a那么a和b指向同一块内存但是当修改a或者b的值得时候,Python会新分配一块内存来存储新的值 python中不可变类型(不支持修改)是数值类型,字符串类型,元组类型,其中数值和字符串全部都是引用,修改本质上是再开辟一块空间存放新值python中可变类型是列表和字典,在字典中,只有不可变类型才能够做key(甚至元组也可以做key) 原文地址:https://www.cnblogs.com/zhanggaofeng/

python 引用和对象理解

今天浏览博客的时候看到这么一句话: python中变量名和对象是分离的:最开始的时候是看到这句话的时候没有反应过来.决定具体搞清楚一下python中变量与对象之间的细节.(其实我感觉应该说 引用和对象分离 更为贴切) 从最开始的变量开始思考: 在python中,如果要使用一个变量,不需要提前进行声明,只需要在用的时候,给这个变量赋值即可 (这个和C语言等静态类型语言不同,和python为动态类型有关). 举第一个栗子: a = 1 这是一个简单的赋值语句,整数 1 为一个对象,a 是一个引用,利

python 引用/copy/deepcopy

1 #coding=utf-8 2 import copy 3 a=[1,2,'a','ab',['c','d']] 4 b=a #只是传引用 5 6 c=copy.copy(a)#copy 7 d=copy.deepcopy(a)#deepcopy 8 9 a.append('f') 10 a[4].append('m') 11 12 print 'a:',a 13 print 'b:',b 14 print 'c:',c 15 print 'd:',d 1 Python 2.7.9 2 Ty

Python引用传值总结

Python函数的参数传值使用的是引用传值,也就是说传的是参数的内存地址值,因此在函数中改变参数的值,函数外也会改变. 这里需要注意的是如果传的参数类型是不可改变的,如String类型.元组类型,函数内如需改变参数的值,则相当于重新新建了一个对象. # 添加了一个string类型的元素添加到末尾 def ChangeList(lis): lis.append('hello i am the addone') print lis return lis = [1, 2, 3] ChangeList(

从python中copy与deepcopy的区别看python引用

讨论copy与deepcopy的区别这个问题要先搞清楚python中的引用.python的内存管理. python中的一切事物皆为对象,并且规定参数的传递都是对象的引用.可能这样说听起来比较难懂,对比一下PHP中的赋值和引用就有大致的概念了.参考下面一段引用: 1. python不允许程序员选择采用传值还是传引用.Python参数传递采用的肯定是“传对象引用”的方式.实际上,这种方式相当于传值和传引用的一种综合.如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当

Python引用的概念

Python中常量的概念其实是对象的概念(所谓在Python中,万物皆对象),所有的赋值操作都是变量对操作数对象的引用.在Python中,每一个变量都有一个独一无二的id,可以称之为变量地址,用id()方法查看(如图1).其中右边的字符串可以看作为一个字符串对象,而左边为这个字符串对象的引用.我们现在通过sys.getrefcount()方法来查看第一次引用时,变量内部的引用计数器的初始值为多少(如图2).此处需要解释一下,一般来说第一次引用它的引用计数器应为1,但此时为2(也会为3或者其他值)