模块分类:
1. 内置模块
2. 第三方模块
3. 自定义模块
py文件的两种功能:
1. 脚本:一个文件就是整个陈旭,用来被执行。
2. 模块:文件中存放着一堆的功能,用来被导入使用。
模块与包
模块:将一些具有相同功能且经常会被使用的代码放在一个py文件中。该py文件就可以叫一个模块。
包:只要文件夹下含有__init__.py文件就是一个包。
导入和加载:
导入:指将py文件导入进内存当中进行后期的使用。(如果需要使用模块方法,那么每次都会进行导入。而不会再重新加载模块内代码了。)
import test #当第一次导入时,会加载所有test内的代码进入到内存。(相当于运行了一遍)
加载:指运行所导入模块内的具体方法。(当第一次导入模块时,会自动加载所导入的模块。并且加载一次后,后面再次导入就不会进行加载。)
import test
print(test.name) #相当于打印已经加载好的name变量。
导入模块:
需要注意点:
1. 导入模块时,只会把当前运行的py文件所属的路径加载到python路径中去,而不会将其他包内的路径一同加入。而使用pycharm时,会将创建的项目路径一同加入到python路径中。而如果使用非pycharm运行时,因为没有加载而出错,所以如果包含多个包的项目,首先将根路径加入。
import os
BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
2. 导入模块时,要尽量小的来导入,如果能使用该模块的大部分功能,那么可以导入所有。如果只用一个,那么最好就使用form来进行导入。
——————————————Day04.py————————————
def a():
print(a)
print(123)
——————————————test.py——————————————
1.
import Day04 #将Day04内所有函数进行导入。
Day04.a()
2.
from Day04 import a #将包中某一个函数单独提取。
a()
3.
from Day04 import * #功效和1一样。
4.
from Day04 import a as f #给a函数重新命名,以免在本函数内有相同命名。
f()
第一次导入模块将执行的三件事:import与from同样效果。
1. 创建一个以模块名命名的名称空间。
2. 执行这个名称空间(即导入的模块)里的代码。
3. 通过此模块名 . 的方式引用该模块里的内容
import的使用
import语句是可以在程序中的任意位置使用的。且针对同一个模块import很多次,为了防止你重复导入,python的优化手段:
1. 第一次导入后就将模块名加载到内存了。
2. 后续的import语句仅对已经加载到内存中的模块对象增加了一次应用,不会重新执行模块内的语句。
起别名:
import test as B
from test import func as x
'''
1. 将很长的模块名改短,方便使用
2. 有利于代码的扩展和优化
'''
导入多个模块:
'''
1. 逐一导入
2. 从小到多的名称导入
'''
import x
import xx
import xxx
from X import *
会把X中的不是以下划线(_)开头的名字都导入到当前位置。
使用all来配合使用。
#test.py
__all__=['func']
print('this is test.py')
def func():
print('this is test.py_func')
def func2():
print('this is test.py_func2')
——————————————————————————————————————————————————
#run.py
from test import *
func()
func2() #由于没有写在all里,将会报错。
执行文件不等于导入文件:
在项目中应尽量避免出现循环/嵌套导入,如果出现多个模块都需要共享的数据,可以将共享的数据集中存放在某一个地方。具体事例可以看练习题2和3加深理解。
用字符串形式来导入模块:
1. getattr
import test
a = getattr(test,'a')
print(a)
2. __import__('模块名')
a = __import__('test')
print(a.a)
3. 导入多次相同的模块,只会使用第一次导入时的加载内容。如果必须要加载两次可以使用:importlib模块。
import importlib
import test1
importlib.reload(test1)
4. 可以通过导入模块来构造出来一个单例模式。相当于只加载一次刚导入的
+++++++++jd.py++++++++
class Foo(object):
pass
obj=Foo()
+++++++++app1+++++++++
import jd
print(jd.obj)
+++++++++app2++++++++++
import jd
print(jd.obj)
__name__的作用:
1. 当文件被当做脚本执行时:__name__=='__main__'
2. 当文件被当做模块导入时:__name__ == 模块名
这样可以用来控制.py文件在不同的应用场景下执行不同的逻辑。
Python引用模块规则及顺序:
1. 内存中已经加载的模块进行寻找
2. 内置模块中寻找
3. sys.path中路径包含的模块中寻找
4. 再没找到就报错。
小练习1
'''
看两个得出结果是否一样,如果不一样为什么。
'''
# test.py
# print('this is test.py')
# def func():
# print('this is test.py_func')
# def func():
# print('24')
# from test import func
# func() #得出的结果
# from test import func
# def func():
# print('24')
# func() #得出的结果
'''
说明当import的名称和现有的方法相冲突时,会覆盖掉前面的内存指向。
'''
小练习2
'''
创建的3个文件,当运行run时,会不会报错,为什么?他们的流程是什么。
如果出错,那么如何改正。
'''
#m1.py
# print('正在导入m1')
# from m2 import y
# x = 'm1'
#m2.py
# print('正在导入m2')
# from m1 import x
# y='m2'
#run.py
# import m1
'''
1. 会报错
2. 运行run,运行m1,运行m2,由于此时m1还在导入m2的过程中,并没有将x导入到内存,所以m2无法导入x,报错。
3. 将from m2 import y 更改到x下面即可
'''
小练习3
'''
运行m1,会不会报错,如果报错是哪里错了。流程是什么
'''
#m1.py
# print('正在导入m1')
# from m2 import y
# x = 'm1'
#m2.py
# print('正在导入m2')
# from m1 import x
# y='m2'
'''
1.打印m1,导入m2
2.打印m2,导入m1
3.打印m1,导入m2,由于已经导入了m2,所以直接要y,没有报错了。
'''