[Python]模块和包

xiaoxiao2021-02-27  333

一、模块和文件 1、模块和文件 模块是按照逻辑来组织Python代码的方法,任何Python源文件都能以模块的形式使用。 一个文件被看做是一个独立模块,一个模块也可以被看做是一个文件。 模块的文件名 =  模块的名字.py 2、搜索路径和路径搜索 搜索路径:是一组目录,如果一个模块不在搜索路径中,会导致路径搜索失败。 路径搜索:在搜索路径中查找某个文件 搜索路径的查看: (1)默认搜索路径是在编译或安装时指定,在启动Python的shell或命令行的PYTHONPATH环境变量。该变量的内容是一组用冒号分割的目录路径。 (2)sys.path变量 >>> import sys >>> sys.path ['', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\python35.zip', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\DLLs', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\lib', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\lib\\site-packages'] 搜索路径的修改: (1)在搜索路径尾部追加目录 sys.path.append() >>> sys.path.append("D:\\SelfStudy\\PythonStudy\\grammar")(2)在指定位置增加目录 sys.path.insert() >>> sys.path.insert(2, "D:\\SelfStudy\\PythonStudy\\pratice") >>> sys.path ['', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\python35.zip', 'D:\\SelfStudy\\PythonStudy\\pratice', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\DLLs', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\lib', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32', 'C:\\Users\\xiaoloaw\\AppData\\Local\\Programs\\Python\\Python35-32\\lib\\site-packages', 'D:\\SelfStudy\\PythonStudy\\grammar'] 二、名称空间 名称空间是名称(标识符)到对象的映射,在执行期间有两个或三个活动的名称空间。 局部名称空间、全局名称空间、内建名称空间。如果在执行期间调用了一个函数,那么将创建出局部名称空间。 通过globals()和locals() 内建函数判断一个名字属于哪个名称空间。 1、名称查找 访问一个属性时,解释器必须在三个名称空间中的一个找到它。 查找顺序是:局部名称空间 ---> 全局名称空间 ---> 内建名称空间 前面空间中找到的名字会隐藏后面空间的名字。 # actionScope.py def foo(): print("calling foo()...") bar = 200 aString = "ha ha" print("in foo(), bar is", bar) # 在局部命名空间中搜索到bar, 屏蔽全局空间中的bar:200 print("------------------------") print("foo()'s globals:", globals().keys()) # globals() 查看全局命名空间中的变量 print("foo()'s locals:", locals().keys()) # locals() 查看局部命名空间中的变量 bar = 100 print("in __main__, bar is", bar) foo() print("------------------------") print("__main__'s globals:", globals().keys()) print("__main__'s locals:", locals().keys()) >>> python actionScope.py in __main__, bar is 100 calling foo()... in foo(), bar is 200 ------------------------ foo()'s globals: dict_keys(['__spec__', 'foo', '__doc__', '__loader__', '__builtins__', '__name__', '__file__', '__package__', '__cached__', 'bar']) foo()'s locals: dict_keys(['aString', 'bar']) ------------------------ __main__'s globals: dict_keys(['__spec__', 'foo', '__doc__', '__loader__', '__builtins__', '__name__', '__file__', '__package__', '__cached__', 'bar']) __main__'s locals: dict_keys(['__spec__', 'foo', '__doc__', '__loader__', '__builtins__', '__name__', '__file__', '__package__', '__cached__', 'bar']) 三、导入模块 1、import语句:使用import语句导入整个模块 首次使用import加载模块时,它将做3件事: (1)创建新的命名空间,用作在相应源文件中定义的所有对象的容器。在模块中定义的函数和方法在使用global语句时将访问该命名空间。 (2)在新创建的命名空间中执行模块中包含的代码 (3)在调用函数中创建名称来引用模块命名空间。这个名称与模块的名称想匹配。 import module1 # 把整个模块导入到当前的名称空间 import module2 ... ... module1.func1() # 在使用的时候需要显示的指定哪个模块中的属性 module2.func2() ... ... import语句的模块顺序: (1)Python标准库模块 (2)Python第三方模块 (3)应用程序自定义模块 2、from-import语句:从模块中导入指定的模块属性 from module import name1 [, name2 [, ... nameN]] # 把指定的模块属性导入到当前的名称空间 name1() # 可以直接使用属性,而不需要指定模块 name2() ... ... from module import * # 把模块的所有名称导入到当前名称空间,可以直接使用属性,不需要指定模块 # 但是这样有可能污染当前名称空间 3、from-import-as语句:将模块的属性重命名 from module import name as nm name() # 直接使用属性 或者 属性的别名 nm() 4、导入(import)、加载(load)、重加载(reload) 加载模块会导致这个模块被"执行",也就是 被导入模块的顶层代码将直接被执行。因此,只把函数和模块定义放入模块的顶层是良好的模块编程习惯。 一个模块只被加载一次,无论被导入多少次。只在第一次导入时被加载。 如果被加载的模块有改动,需要调用reload()函数重新加载该模块。 import imp imp.reload(module) 使用reload()的时候有一些标准: (1)模块必须是全部导入(不是使用from-import),并且它必须被成功导入。 (2)reload()函数的参数必须是模块自身,而不是包含模块名的字符串。类似reload(sys),而不是reload('sys')。 关于reload()的更多用法,请参考 点击打开链接 5、被导入模块和导入模块的作用域 被导入者imptee.py 和导入者impter.py # imptee.py foo = 'abc' def show(): print('foo from imptee:', foo) # impter.py from imptee import foo, show show() foo = 123 print('foo from impter:', foo) # 被导入的变量只会影响到局部,而不是整个命名空间 show() # 运行结果 foo from imptee: abc foo from impter: 123 foo from imptee: abc # impter02.py import imptee imptee.show() imptee.foo = 123 # 显式的设置变量 print('foo from impter:', imptee.foo) imptee.show() # 运行结果 foo from imptee: abc foo from impter: 123 foo from imptee: 123 四、包 包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用程序执行环境。 包可以解决以下问题: (1)为平坦的名称空间加入有层次的组织结构 (2)把有联系的模块组合到一起, (3)使用目录结构而不是一堆混乱的文件 (4)解决有冲突的模块名称 1、导入包 Phone ├── __init__.py ├── common_util.py ├── Fax │ ├── __init__.py │ └── Ga.py ├── Mobile | ├── __init__.py │ ├── Analog.py │ └── Digital.py └── Voicedta ├── __init__.py ├── Isdn.py └── Pots.py # Phone是最顶层的包,Mobile,Fax等是它的子包 导入包的方法有: (1)使用import,指定完整的路径 import Phone.Mobile.Analog Phone.Mobile.Analog.dial() (2)from-import from Phone import Mobile # 只导入顶层的子包,使用点操作符访问 Mobile.Analog.dial('1234-999') from Phone.Mobile import Analog    # 引入更多的子包 Analog.dial('1234-999') from Phone.Mobile.Analog import dial   # 沿子包的树状结构导入 dial('1234-999') 注:在使用from-import语句导入子包时需要用到__init__.py,如果没有用到,他们可以是空文件。 因此在创建包时,需要在每次目录中增加这个文件。 五、导入循环 在大型的Python工程中,由于架构设计不当,可能会出现模块间相互引用的情况。 这时候需要通过一些方法来解决这个问题. (1)重新设计架构,解除相互引用的关系。 (2)把import语句放置在模块的最后 (3)把import语句放置在函数中 具体请参考 点击打开链接
转载请注明原文地址: https://www.6miu.com/read-3083.html

最新回复(0)