python语言之所以能够被广泛使用,很大程度上得益于它的模块化系统。python封装了功能丰富的标准库让用户使用,另外开发者还可以根据自己的需求不断为python增加扩展库。

1 模块化编程

1.1 导入模块的语法

1、使用import导入模块:
import 模块名1[as别名] ,模块名2[as别名2],…:导入整个模块。
from 模块名 import成员名1[as别名1],成员名2[as别名2],…:导入模块中指定成员。

from sys import * #导入模块所有成员
import sys as s #导入模块并命名

1.2 定义模块

模块就是python程序!任何python程序都可以作为模块导入。

print('这是module 1')
my_book = '疯狂python讲义'
def say_hi(user):
    print('%s,您好,欢迎学习python'%user)
class User:
    def __init__(self,name):
        self.name = name
    def walk(self):
        print('%s正在慢慢地走路'% self.name)
    def __repr__(self):
        return 'User[name=%s]'% self.name

模块的文件名就是模块的名称,例如别的文件中可以通过import module1引入这个模块。

1.3 为模块编写说明文档

为模块编写说明文档就是在模块开始处,定义一个字符串直接量即可。

'''
这是我编写的第一个模块
希望大家尽情复用
'''
print('这是module 1')
my_book = '疯狂python讲义'
def say_hi(user):
    print('%s,您好,欢迎学习python'%user)
class User:
    def __init__(self,name):
        self.name = name
    def walk(self):
        print('%s正在慢慢地走路'% self.name)
    def __repr__(self):
        return 'User[name=%s]'% self.name

1.4 为模块编写测试代码

这个内容很简单,有一点需要注意的就是,写模块测试代码时需要利用所有模块内置的__name__属性判断是否执行该模块的命令。直接运行该模块,会执行测试函数。

'''
这是我编写的第一个模块
希望大家尽情复用
'''
print('这是module 1')
my_book = '疯狂python讲义'
def say_hi(user):
    print('%s,您好,欢迎学习python'%user)
class User:
    def __init__(self,name):
        self.name = name
    def walk(self):
        print('%s正在慢慢地走路'% self.name)
    def __repr__(self):
        return 'User[name=%s]'% self.name

#================================以下是测试代码====================
def test_my_book():
    print(my_book)
def test_say():
    say_hi('悟空')
def test_User():
    u = User('白骨精')
    u.walk()
    print(u)

if __name__ == '__main__':
    test_my_book()
    test_say()
    test_User()

2 加载模块

为了让python知道在哪里才能找到我们编写的python模块看,可以通过两种方式告诉python编译器。
1、使用环境比哪里
2、将模块放在默认的模块加载路径下。

2.1 使用环境变量

python会根据PYTHONPATH环境变量的值确定到哪里去加载模块。PYTHONPATH环境变量的值是多个路径的集合,这样python会一次搜索PYTHONPATH环境变量所指向的多个路径,试图从中找到程序想要加载的模块。
1、在windows设置环境变量。
一般建议设置“用户变量”即可,因为用户变量只对当前用户有效。而系统变量对所有用户有效。
添加环境变量的操作相对简单,大家可自行百度解决。有一点要注意的就是添加环境变量的名称为PYTHONPATH.
2、在其他操作系统上设置环境变量
大家百度自行解决,没有什么难度。

2.2 默认的模块加载路径

如果要安装通用性模块,比如复数功能支持的模块,矩阵计算支持的模块、图形界面支持模块,这些都属于对python本身进行扩展的模块,这种模块应该直接安装在python内部,以便被所有程序共享。
python默认的模块加载路径由sys.path变量代表,通常应该将python的扩展模块添加在lib\site-packages路径下,它专门用于存放python的扩展模块和包。

2.3 导入模块的本质

导入模块的本质就是将模块中的代码全部加载到内存中并执行,然后将整个模块的内容赋值给与模块同名的变量,在模块中定义的所有程序单元都相当于试该变量的成员。
在导入模块后,可以在模块文件所在目录下看到一个名为“–pycahe–”的文件夹,打开该文件夹,可以看到python为每个模块都生成一个*.cpython-38.pyc文件,该文件其实是python为模块编译而生成的字节码,用于提高该模块的执行效率。

2.4 模块的__all__变量

如果使用from模块名import *导入模块,程序会导入该模块中所有不以下滑线开头的程序单元。
有时模块虽然包含很多程序单元,但并不希望每个成员都暴露出来供外界使用,可以使用–all–变量,将变量的值设置为一个列表,只有该列表中的程序单元才会暴露出来。

def hello():
    print('hello python')
def world():
    print('python world is funny')
def test():
    print('---test----')
__all__ = ['hello','world']

在另外一个Python文件中导入该模块,并使用模块中定义的函数。

from all_module import  *
hello()
world()
test()#因为接口没有暴露该函数会报错

事实上,__all__变量的意义在于为模块定义了一个开放的公开接口,通常来说只有__all__变量列出来的程序单元,才是希望被外界使用的程序单元。
另外,如果的确希望使用模块内部__all_变量之外的程序单元,有两种解决方法。
1、使用import模块名导入模块。
2、使用from模块名import程序单元导入指定程序单元。

3 使用包

3.1 什么是包

1、从物理上来看,包就是一个文件夹,在该文件夹下包含了一个__ini__.py文件,该文件夹用于包含多个模块源文件。
2、从逻辑上看,包的本质还是模块。
包的本质就是模块,因此包可以包含包。

3.2 定义包

定义一个包,主要有两步:
1、创建一个文件夹,该文件夹的名称就是包名。
2、在该文件夹内添加一个__ini__.py文件即可。

下面给出一个建包的示例,该包包含三个模块文件:
fk_package
–>arithmetic_chart.py
–>billing.py
–>pirnt_shape.py
–> --ini–.py
.\fk_package\arithmetic_chart.py

def print_multiple_chart(n):
    '打印乘法口诀的函数'
    for i in range(n):
        for j in range (i+1):
            print('%d = %2d'%(j+1),(i+1),(j+1)*(i+1),end= ' ')
        print('')

.\fk_package\billling.py

class Item:
    '定义代表商品的Item类'
    def __init__(self,price):
        self.price = price
    def __repr__(self):
        return 'Item[price = %g]'% self.price

.\fk_package\print_shape.py

def print_blank_triangle(n):
    '打印一个由星号组成的三角形'
    if n <= 0:
        raise  ValueError('n必须大于0')
    for i in range(n):
        print(' '*(n-i-1),end='')
        print('*',end='')
        if i != n-1:
            print(' '*(2*i -1), end='')
        else:
            print('*'*(2*i-1),end='')
        if i !=0:
            print('*')
        else:
            print('')

fk_package下的__ini__.py文件暂时为空。

3.3 导入包内成员

下面通过一个例子使用之前定义的三个模块。
.\fk_package_test.py

import  fk_package#因为__ini__py文件为空,这一句没有作用
import  fk_package.print_shape
from fk_package import billling
import fk_package.arithemetic_chart
fk_package.print_shape.print_blank_triagle(5)
im = billling.Item(4.5)
print(im)

可以看出import fk_package就是将fk_package目录下单__ini__.py文件中定义的程序单元导入程序中。
可以在__ini__.py导入模块的程序单元方便后续使用,如下定义fk_package的__ini__.py文件:

#从当前包中导入print_shape模块
from . import  print_shape
#从.print_shape导入所有程序单元到fk_package中
from .print_shape import *
#从当前包中导入billling模块
from . import  billling
#从.billing导入所有程序单元到fk_package中
from .billling import *
#从当前包中导入arithmetiac_chart模块
from . import  arithmetic_chart
form . arthmetic_chart  import *

之后再使用改包就变得简单了。

import fk_package
fk_package.print.blank_triangle(5)#直接通过包调用

4查看模块内容

4.1 模块包含什么

可以通过两种方式来查看模块包含些什么:
1 使用dir()函数
该函数可以用于返回模块或类所包含的全部程序单元(变量、函数、类和方法),但直接使用dir()函数默认会列出模块内的所有程序单元,为了过滤其中下滑线(一般下滑线并不希望被外部调用)

[e for e in dir(string) if not  e.startwith('_')]
#---------下面是python解释器显示的----------------------------
['Formatter', 'Template', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']

2、使用__all__变量查看模块内的程序单元

4.2 使用__doc__属性查看文档

可以用过help()函数查看程序单元的帮助信息,比如导入string模块之后,就可以可使用help函数查看指定程序单元的帮助信息。

python import的参数能不能修改 python __import__()_环境变量


help函数之所以能够看到程序单元的帮助信息,完全是因为该程序单元本书由文档信息,也就是由__doc__属性,使用help()函数查看的其实就是程序单元的__doc__属性。

4.3 使用__file__属性查看模块的源文件路径

通过模块的__file__属性可以查看指定模块的源文件路径,另外,并不是所有的模块都是使用Python语言编写的,有些与底层交互的模块可能是c语言编写的,而且是c程序编译之后的效果,因此这种模块可能没有__file__属性。