python-模块化

一、基本概念

  • 模块:即代码的一种组织方式,将实现相关功能的代码组织在一起;包、模块是同一种概念,只是模块用于代表一个.py文件,而包只的是一个文件夹,里头可以由模块、子包;

  • 包:一种组织方式,一个文件夹,由模块和子包组成;

导入模块的本质:即在当前的.py文件中加载其他模块、包、其他对象(可以是属性、类、实例、各种标识符代表的对象),赋值给一个标识符(包、模块、其他对象的名称)或者自定义名称;

二、使用方式

常用的内建函数(方法)

import sys
print(dir())					#当前环境可以使用的变量,返回的是一个列表
print(global())					#当前环境可以使用的的全局变量
print(local())					#当前环境可以使用的本地变量
print(__name__)					#取当前模块名称,在当前模块运行即__main__模块
print(sys.path)					#变量的查找顺序
print(sys.modules)				#当前加载的模块
print(moudle.__dict__)			#模块的属性
print(__file__)					#模块的路径

查看当前环境能够使用的标识符;标识符指向的是一个模块

import sys
import random
import os
import os.path

print(dir())
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'os', 'random', 'sys']

如何理解dir()、globals()、locals()

#dir()、globals()、locals()这三个内建函数都是与当前环境相关;
#定义在函数中,当前环境就是关于函数的变量;定义在顶层代码中,就是关于本模块全局的;
def A():
    a = 100
    b = 200
    print(dir())			#当前环境即函数内,能够使用的变量
    print(globals())		#全局环境能够使用的变量
    print(locals())			#当前函数内,能够使用的本地变量

A()

模块的查找路径

import sys

print(*sys.path,sep = '\n')

C:\Users\DELL\PycharmProjects\pythonProject
C:\Users\DELL\PycharmProjects\pythonProject
C:\Users\DELL\venvs\t1\Scripts\python36.zip
C:\Python\Python365\DLLs
C:\Python\Python365\lib
C:\Python\Python365
C:\Users\DELL\venvs\t1
C:\Users\DELL\venvs\t1\lib\site-packages

#1、当前的项目目录
#2、标准库
#3、windows下的动态链接库
#4、标准库、第三方依赖
#5、虚拟环境目录
#6、虚拟环境的库

1、引入方式

import

  • 使用import导入全局/本地标识符,这个标识符指向一个模块对象,可使用该模块的资源了;

  • import后面跟的必须是一个模块

  • 导入非顶级模块,只能将其加入到本地的名词空间中(locals、dir()),导入的模块必须使用完全限定名来访问;

  • 如果使用了as,这as以后定义的名称会绑定到模块;

#在顶级代码中引入模块,赋予os这个变量(标识符)指向os模块;
#访问os模块中的资源os.xxx
import os				#可以理解为   os(标识符) ---->  os模块

print(dir())
print(os.path.exists('F:/log.txt'))
#在函数中引入模块,该变量(标识符)在函数本地范围有效;
def a():
    import os
    if os.path.exists('F:/log.txt'):
        os.remove('F:/log.txt')
        print('removed file')
    else:
        with open('F:/log.txt','w') as f:
            f.write('66666')
            print('writed file')
a()
print(dir())

如何理解import os / import os.path 这两种方式

import os 
print(os.__file__)
print(os.path.__file__)
print(dir())

1、import os
加载的是os模块,需要使用的path类话必须使用限定名即os.path;
当前环境能够使用的变量(标识符)是os

os.path
os.stat
os.remove

2、import os.path
加载的模块是os,需要使用的话必须使用限定名os.path
当前环境的变量(标识符)是os
能够只能使用os.path

os.path

from … import …

  • from后面跟的必须是模块,加载并初始化它,此时并没有导入,import以后即加载模块并加载import后的函数、类、变量、常量、模块等等;

  • import 后面可以跟函数、类、变量、常量、模块、*

    对于import后面的子句:

    1、首先查from子句加载的模块是否有该属性;

    2、如果不是,则尝试导入导入该名称的子模块

    3、如果没有找到,则抛出异常ImportError

    4、如果这个名称被保存到本地的名词空间中,如果有as子句,则使用as子句后的名称;

from os import path
from functools import warps,update_wrapper,partal,lru_cache

print(dir())
print(path.exists('F:/t1.log'))

三、自定义模块

什么是自定义模块?

即自定义写的.py文件,将相同类型功能的代码组织在一起,其他的文件可以引用到这个模块中的对象;
#模块t1.py
class Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def show(self):
        return self.x,self.y


t = Point(4,5)

a = 100
b = 200

第一种方式import t1,t1标识符赋值,指向t1这个模块,能够使用限定名访问t1模块下的所有属性;

#t2.py
import t1					#引入t1模块
print(t1.__dict__.keys())	
print(t1.Point)
print(t1.t)
print(t1.a)
print(t1.b)
print(t1.t.show())

第二种方式,from t1 import t,t标识符复制,指向模块t1下的实例t,能够访问到实例下的属性;

#t2.py
from t1 import t
print(t.show())
print(t.x)
print(t.y)
print(t.__dict__)
print(dir(t))

模块化特性总结

  • 每个模块都有独立的变量(模块全局的、模块局部的),他们的范围都在当前模块下;其他模块(文件)需要使用则需要引入该模块;引入的方式有两种;

  • 引入模块的本质是加载模块,即将引入的模块中的代码跑一遍;然后将标识符赋值(模块名称赋值给标识符),指向这个模块;

    import t1:加载这个模块,标识符赋值,模块下所有资源可用;

    from t1 import Point:加载这个模块,标识符赋值,指向模块下的某一个类;只有类资源可用;也可以实例化,使用实例资源(需要赋值在使用)

  • 在当前模块运行,当前模块的名字会被修改成 main(主模块)

    当在t2.py中运行,则显示名称为__main__;

    在t2.py中调用 t1.__name__则显示名称为t1;

  • 模块命名的规范:在import的时候,模块名称赋予的标识符,所以模块名称与变量命令一样,不允许与标准库或者第三方库中的模块名/变量名冲突;

四、模块的运行

当从标准输入(命令行方式敲代码)、脚本($ python test.py)或交互式读取的时候,会将模块的__name__设置为__main__,模块的顶层代码就在__main__这个作用域中执行。

顶层代码:模块中缩进最外层的代码。如果是import导入的,其__name__默认就是模块名

即当标准输入和运行脚本的时候,实际上是运行的__main__(在哪个.py文件运行哪个就是主模块__main__)

当t2.py作为主模块时,import t1 会加载t1;
此时运行t2,t1会被加载,这种情况下t1的模块名为t1,进入else字句;
应用场景:
1、可以用于非主模块的功能测试,将测试代码写入if __name__ == '__main__'中,然后以非主模块运行,则运行的是测试代码;而当真正的主模块运行的时候,运行的是业务代码;

2、主模块变更,当前主模块没有封装;
   在需要进行主模块变更是,import 当前主模块,运行新的住模块时,老的主模块会一并运行;

代码测试:

	#t1.py
		
	if __name__ == '__main__':
	    print('-----------------')
	    print('i am {}'.format(__name__))
		print('这里可以写入测试代码')
	else:
	    print('----------------')
	    print('i am {}'.format(__name__))
	    class Point:
	        def __init__(self,x,y):
	            self.x = x
	            self.y = y
	
	        def show(self):
	            return self.x,self.y
	
	    t = Point(4,5)
	
	    a = 100
	    b = 200
	    print('===================')


	#t2.py(主模块)
	import t1

主模块变更:

	#t1.py

		
	if __name__ == '__main__':
	    print('-----------------')
	    print('i am {}'.format(__name__))
	    print('这里可以写入测试代码')
	else:
	    print('----------------')
	    print('i am {}'.format(__name__))
	    class Point:
	        def __init__(self,x,y):
	            self.x = x
	            self.y = y
	
	        def show(self):
	            return self.x,self.y
	
	    t = Point(4,5)
	
	    a = 100
	    b = 200
	    print('===================')	

	#t2.py(原主模块)

	if __name__ == '__main__':
	    import t1
	    print(t1.a)
	
	else:
	    a = 10000
	    b = 20000

	#t3.py(新主模块)

	import t1
	import t2
	print(t2.a)
	print(t1.a)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值