python模块与包
导入模块的两种方法
import
导入文件最简单的方式就是import,它的语法为
import 导入模块名 [as 模块别名]
这种方式的原理是:将该模块导入内存中,在项目中建立一个该模块的引用,类似于命名空间,我们可以通过这个引用来使用这个模块里的函数或属性,多个项目导入同一个模块时,内存中的模块不会复制,也就是说,程序间会相互影响,比较简单,不再举例。
当我们使用模块内的成员的时候,我们需要在成员名前加上模块的名字,如果使用了as给模块的引用取了别名,则需要使用别名
from import
from import的语法为
from 导入模块名/包名 import 模块的成员
其中模块的成员可以是对象,函数,类等,可以用*代表__all__包含的成员成员,如果该模块没有__all__,则包含所有不以双下划线开头的成员
这种方式的原理是:将该模块的成员直接复制到项目中,所以,我们在使用模块的成员时可以不用加引用
注意:如果该项目原先有成员和导入模块的成员重名,或者后来又定义了和导入模块的成员重名的成员,那么根据Python的机制,原先的将会被覆盖掉,所以这种方式有一定的风险,但使用很方便,例如
def floor(x):
return '我是'+str(x)
print(floor(1.1))
from math import *
print(floor(1.1))
结果为
我是1.1
1
小问题
这里有一个奇怪的现象,似乎和我想的不太一样,比如这种情况
# hello.py
a = '我才是真的a'
print(a)
from testm import *
print(a)
fun()
a = '我才是a'
print(a)
fun()
# testm.py
a = '我是a'
def fun():
print(a)
执行hello.py后,结果为
我才是真的a
我是a
我是a
我才是a
我是a
我们来分析一下:
-
第一行的‘我才是真的a’很简单,在hello定义了一个str类型的a,里面是’我才是真的a’,输出结果也就是’我才是真的a’
-
第二行的’我是a’也很简单导入testm后,原来的a就被testm里的a覆盖了,输出的自然就是’我是a’了
-
第三行的’我是a’也是同样的道理,fun函数输出a,这里的a无论是在hello里还是在testm里都是’我是a’
-
第四行的’我才是a’是因为我把用’我才是a’的引用把a里的’我是a’的引用覆盖了,所以输出的就是’我才是a’
-
第五行的’我是a’就不太理解了,似乎是因为命名空间是不同的,但testm又可以覆盖掉hello里的a变量
这里,我的推测如下
testm.py
和hello.py
其实工作在不同的工作空间,当hello.py
执行from testm improt *
时,会在内存中为testm
创建一个新的工作空间,同时,将a
和fun
的引用复制过去,这里要说明一点,在Python中,所有的变量里的内容都是引用,也就是说这里其实a
和fun
只是引用的名字,我们只是将这个名字和引用复制过去,所以会将重名的引用给覆盖掉,a
变成了'我是a'
的引用。当在hello里调用fun
时,它会通过fun
的引用来在testm
的工作空间执行,所以无论在hello
中的a
引用怎么变换,在testm
中都不会变。
而当你使用import时,当我们修改a时,会修改hello的a,当我们修改testm.a时,会通过testm找到testm的工作空间,然后修改testm里的a,非常好理解
__name__
通常用来判断当前模块是不是主程序,如果是,__name__
的值就是"main",否则,就是当前模块名
搜索路径
搜索路径是Python搜索模块的路径,如果导入的模块不在搜索路径中,那么将导入失败
当我们用IDEL打开一个模块时,会自动将该模块的路径加入搜索路径中
要想查看搜索路径,则需要导入sys模块,sys.path列表的值就是搜索路径,可以修改它来修改搜索路径
包package
类似于java包的概念,就是保存一些模块的文件夹
创建一个包的步骤如下
-
创建一个文件夹,文件夹名就是包名
-
将想要放入其中的模块文件放入该文件夹中
-
在文件夹中创建一个
__init__.py
的模块文件,内容可以为空,用来告诉Python这是一个包,这个包中有哪些类或方法,若要外部要从包中导入某个类/方法,可以在__init__.py
内写如下内容from .类/方法所在模块名 import 类/方法
注意:这里的点表示当前路径,
.模块名
表示包内的模块,
导入的时候,与直接导入模块一样,只是模块名变为包名.模块名
注意,包的位置也应该在搜索路径下,否则一样无法找到模块
例如,我在搜索路径下创建了一个m1文件夹,里面放入了一个te1.py模块,并创建了一个空的__init__.py
模块。这时,要想导入te1模块,可以使用下面语句
import m1.te1#也可以使用from m1 import te1