1.from 。。。import xxx
例:
from my_moudle import login
1)from import 的时候发生了什么
①先找到my_moudle模块
②开辟一块属于这个模块的命名空间
③执行这个模块(将模块中的变量、函数等加载到命名空间)
#对于后半段import login
④知道了要import的是login这个名字,那么就会在本文件中创建一个变量login,指向模块命名空间中的login函数
注:如果在本文件中也存在一个login的函数,那么调用login()就会执行本文件中的login,因为本文件中之前指向模块中login()函数的变量login指向了当前文件的login()函数(即当模块中导入的方法或者变量和本文件重名的时候,那么这个名字只代表最后一次对它赋值的那个方法或变量)
模块:my_moudle.py def login(): print("这是一个登陆函数") name = "阿狸" 主程序 from my_moudle import login def login(): print("In my login") login() 输出: In my login
2)在import的时候命名空间的变换
导入了什么,就能使用什么,不导入变量,不能使用,不导入并不意味着不存,而是没有建立我呢见到模块中其他名字的引用
#模块: name = "拉克丝" def login(): print("这是一个登陆函数",name) name = "阿狸" 主程序: from my_moudle import login name = "泽拉斯" login() 输出: 这是一个登陆函数 阿狸
注:在本文件中对全局变量的修改是完全不会影响到模块中的变量引用的
3)重命名
#重命名修改的是本文件中指向模块中函数名的变量名,无法改变模块名
from my_moudle import login as l l() 输出: 这是一个登陆函数 阿狸
4)一行导入多个函数或变量
--------------------------------------- name = "拉克丝" def login(): print("这是一个登陆函数",name) name = "阿狸" ------------------------------------------ from my_moudle import login,name login() print(name) name = "泽拉斯" login() print(name) ------------------------------------------- 输出: 这是一个登陆函数 阿狸 阿狸 这是一个登陆函数 阿狸 泽拉斯
#导入多个模块之后再重命名
from my_moudle import login as l,name as n l() print(n) 输出: 这是一个登陆函数 阿狸 阿狸
5)from 模块 import *
作用:在模块中所有的函数或变量,在本文件中都会生成一个同名的变量引用这些模块和变量
from my_moudle import * login() print(name) 输出: 这是一个登陆函数 阿狸 阿狸
6) * 和___all__ 的相关性
作用:_all__可以控制*导入的内容
---------------------------------- __all__ = ['login'] #必须是这种格式,大括号中写入的必须为字符串 name = "拉克丝" def login(): print("这是一个登陆函数",name) name = "阿狸" --------------------------------------- from my_moudle import * login() print(name) ---------------------------------------- 输出: NameError: name 'name' is not defined #在模块中未加入到__all__的括号中 这是一个登陆函数 阿狸
2.把模块当做脚本执行
补充:
#__name__就相当于__main__
print(__name__) print(type(__name__)) 输出: __main__ <class 'str'>
注:__name__是个变量,随着文件执行当前这个文件还是以导入的方式执行这个文件,__name__的值是变化的
--------------------------- 模块: print(__name__) print(type(__name__)) ---------------------------- 主程序: import my_moudle ----------------------------- 输出: my_moudle <class 'str'>
#当在本文件中执行的时候,输出内容;当以导入模块的方式执行的程序的时候不执行模块中的输出
模块文件: if __name__ == "__main__": print(__name__) print(type(__name__)) 模块文件执行输出: __main__ <class 'str'> 主程序: import my_moudle 主程序不输出内容
1)运行一个py文件的两种方式
①以模块的形式运行(导入模块,即运行模块中的代码)
import my_moudle
②直接在pycharm运行(run运行)、以cmd运行(即以脚本的形式运行)
2)把模块当做脚本执行的时候,需要在本文件中直接打印的代码上加上【if __name__ == '__main__'】;在编写py文件的时候,所有不再函数和类中封装的内容都应该写在【if __name__ == '__main__'】下面
②sys.modules存储了所有导入的文件的名字和这个文件的内存地址,如{'sys':'sys文件的内存地址'}
③只要运行的是当前的文件,才把当前的文件的内存地址存在__main__下面
3)反射自己模块中的内容
结论:只要反射本模块中的内容,就写:
import sys
getattr(sys.modules[__name__],'变量名')
例1:
------------------------------------ my_moudle.py模块 def login(): print("这是一个登陆函数",name) name = "阿狸" if __name__ == "__main__": print(__name__) print(type(__name__)) import sys my_moudles = sys.modules[__name__] getattr(my_moudles,'login')() --------------------------------------------------------------- 主程序 import my_moudle 输出: 这是一个登陆函数 阿狸
例2:
#如果在当前模块,则__name__就等价于__main__
import sys print(__name__) print(sys.modules[__name__]) print(sys.modules['__main__']) #获取当前文件的内存地址 输出: __main__ <module '__main__' from 'E:/python/project/untitled/练习/my_moudle.py'> <module '__main__' from 'E:/python/project/untitled/练习/my_moudle.py'>
#如果此时在主程序中import 这个模块,那么在主程序中__name__就成为__main__,而在模块my_moudle中__name__就为my_moudle
---------------------------------------- import sys print(__name__) print(sys.modules[__name__]) print(sys.modules['__main__']) ---------------------------------------- import my_moudle print(__name__) ----------------------------------------- my_moudle <module 'my_moudle' from 'E:\python\project\untitled\练习\my_moudle.py'> <module '__main__' from 'E:/python/project/untitled/练习/基础代码练习.py'> __main__
#正常情况下反射当前模块中的内容
import sys print(__name__) print(sys.modules[__name__]) print(sys.modules['__main__']) def login(): print("登陆。。。") a = sys.modules["__main__"] getattr(a,'login')() 输出: __main__ <module '__main__' from 'E:/python/project/untitled/练习/my_moudle.py'> <module '__main__' from 'E:/python/project/untitled/练习/my_moudle.py'> 登陆。。。
#如果在主程序中,import导入上述模块,就会出错,因为在主程序中__main__表示的就是当前的程序了(即主程序),所以如果要在主程序中使用上述模块,需要把__main__改为__name__
----------------------------------- import sys print(__name__) print(sys.modules[__name__]) print(sys.modules['__main__']) def login(): print("登陆。。。") a = sys.modules[__name__] getattr(a,'login')() ------------------------------------ import my_moudle ------------------------------------ 输出: my_moudle <module 'my_moudle' from 'E:\python\project\untitled\练习\my_moudle.py'> <module '__main__' from 'E:/python/project/untitled/练习/基础代码练习.py'> 登陆。。。
3.pyc编译文件和重新加载模块
1)pyc编译文件
当把一个脚本当作一个模块执行的时候(即一个文件作为一个脚本被导入的时候),就会在这个文件所在的目录的__pycache__下生成一个编译好的文件,为了之后导入这个文件的时候直接读这个编译好的pyc文件就可以,可以节省一些导入时候的时间
2)重新加载模块
在import一个模块之后,再修改这个被导入的模块,程序是感知不到的;通过importlib中的reload这个函数可以强制程序再重新导入这个模块一次,但是非常非常不推荐
4.模块的循环引用
在模块的导入中,不要产生循环引用问题,如果发生了循环导入模块问题,就会报错(即明明程序写在这个模块中的方法,却显示找不到)
5.包
1)什么是包
集合了一组py文件,提供了一组复杂功能的东西(即一个带有__init__文件的文件夹)
2)为什么要有包
当提供的功能比较复杂,一个py文件写不下的时候,就用到了包
3)包中都有什么
①包中至少拥有一个__init__.py文件
4)包的使用
①直接导入模块,方式一(可以使用重命名的方式)
import 包.包.模块 #导入
包.包.模块.变量 #使用变了
②直接导入模块,方式二(推荐以下方式)
from 包.包 import 模块 #导入
模块.变量 #使用
③导入包
导入包,就相当于执行了这个包下面的__init__.py文件
5)包的导入
①包中模块的绝对导入
②包中模块的相对导入:使用了相对导入的模块只能被到做模块来执行,不能被当作脚本来执行
注:如果希望导入包之后,模块能够正常的使用,那么需要自己去完成__init__文件的开发
总结:
1)import 模块
导入这个模块之后,模块中的所有名字都以通过模块来引用了,即【模块名.名字】
2)from 模块 import 名字
导入这个模块中的某个名字之后,这个名字就可以直接使用了
①如果是变量,直接通过【名字】使用
②如果是函数,直接通过【名字()】调用
③如果是类,直接通过【名字()】实例化对象
3)模块循环引用:模块的引用不能成环
4)把模块当初脚本运行
当希望把一段代码当做模块导入的时候,不要执行,就把这一块代码写在 if __name__ == '__main__'下面
5)sys.path
一个模块(自定义模块),能否被导入,就看sys.path列表中有没有这个模块所在的绝对路径(ModuleNotFoundError)
6)包
从包中导入模块,要注意这个包所在的目录是否在sys.path中
如果是直接导入一个包,那么相当于执行了这个包中的__init__文件,并不会帮你把这个包下面的其他包以及py文件自动的导入到内存
如果希望直接导入包之后,所有的这个包下面的其他包以及py文件都能直接通过包来引用,那么就要自己处理__init__方法