python 模块与包

模块与包是任何大型程序的核心,就连Python安装程序本身也是一个包。本章重点涉及有关模块和包的常用编程技术,例如如何组织包、把大型模块分割成多个文件、创建命名空间包。同时,也给出了让你自定义导入语句的秘籍。

模块

模块简介

模块是一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py 在一个模块内部,模块名(作为一个字符串)可以通过全局变量 name 的值获得。
比如你可以创建一个 myfiles.py 的模块,简单来说模块也就是一个py文件而已。

举例

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):   # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

这就是一个模块,只不过它的功能比较简单,特别要注意的是我们模块调用前,需要我们将工作路径调到我们python模块的路径。
在这里插入图片描述
调用模块里面的功能有两种方法:

  • 直接调用这个py文件(这个要求就是模块不大,里面功能相对少很多)
  • 调用py文件中某一个函数或者参数(这种要求就是我们调用模块的一部分,不是要求调用整个模块)
    在这里插入图片描述
    还有一种就是from fac_1 import *,但这个*号里面要在__all__里面先声明。

简化函数名

如果你想经常使用某个函数,你可以把它赋值给一个局部变量

fib = fibo.fib
fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
 from fibo import *
 fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

这会调入所有非以下划线(_)开头的名称。 在多数情况下,Python程序员都不会使用这个功能,因为它在解释器中引入了一组未知的名称,而它们很可能会覆盖一些你已经定义过的东西。
注意通常情况下从一个模块或者包内调入 * 的做法是不太被接受的, 因为这通常会导致代码的可读性很差。不过,在交互式编译器中为了节省打字可以这么用。

简化模块名

如果模块名称之后带有 as,则跟在 as 之后的名称将直接绑定到所导入的模块。

from fibo import fib as fibonacci
fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

编译过的Python文件

python文件的后缀名有.py和pyc这两种,但pyc一般是编译过的Python文件,这样为的是提高程序的运行速率,下次调用这个py文件就不需要编译,相对来说速率提升了很多,下面我引用了python官方文档的一段话作为参考。

为了加速模块载入,Python在 pycache 目录里缓存了每个模块的编译后版本,名称为 module.version.pyc ,其中名称中的版本字段对编译文件的格式进行编码; 它一般使用Python版本号。例如,在CPython版本3.3中,spam.py的编译版本将被缓存为 pycache/spam.cpython-33.pyc。此命名约定允许来自不同发行版和不同版本的Python的已编译模块共存。
Python根据编译版本检查源的修改日期,以查看它是否已过期并需要重新编译。这是一个完全自动化的过程。此外,编译的模块与平台无关,因此可以在具有不同体系结构的系统之间共享相同的库。
Python在两种情况下不会检查缓存。首先,对于从命令行直接载入的模块,它从来都是重新编译并且不存储编译结果;其次,如果没有源模块,它不会检查缓存。为了支持无源文件(仅编译)发行版本, 编译模块必须是在源目录下,并且绝对不能有源模块。
模块我大致介绍到这里了,有兴趣的可以网上多查阅一下相关资料。

多个功能相似的模块可以组织成一个包, Python中的模块包括系统模块、第三方模块和用户自定义模块。它们实质上是以.py为扩展名的Python文件 。
包相对一个封装的过程,把多个py文件封装在一起,按照一定的目录格式生成,代码组织成由很多分层模块构成的包。封装成包是很简单的。在文件系统上组织你的代码,并确保每个目录都定义了一个__init__.py文件。包是Python引入的分层次的文件目录结构,它定义了一个由 模块及子包,和子包下的子包等组成的 Python 的应用环境。 引入了包以后,只要顶层的包名不与别人冲突,那所有模块都不会与别人冲突。
模块和包最大区别就是__init__.py文件,这个是包的标志。每一个Python的包目录下面都会有名为__init__.py的特殊文件, 该文件可以为空文件,但是必须存在,它表明这个目录不是普通的目录结构,而是一个包,里面包含模块。
在这里插入图片描述

包的分层结构示范

graphics/
    __init__.py
    primitive/
        __init__.py
        line.py
        fill.py
        text.py
    formats/
        __init__.py
        png.py
        jpg.py

下面我简单介绍一下Python包里面几个py文件。

setup.py

setup主要就是对你的包一个介绍和说明。
在这里插入图片描述

__init__文件介绍

init_.py 文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有__init__.py 文件。
通常__init__.py 文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的__init__.py文件。这样我们可以在__init__.py文件中批量导入我们所需要的模块,而不再需要一个一个的导入。

# __init__.py
import re
import urllib
import sys
import os
# a.py
import package 
print(package.re, package.urllib, package.sys, package.os)#注意这里访问__init__.py文件中的引用文件,需要加上包名。

__init__.py中还有一个重要的变量,__all__, 它用来将模块全部导入。
################
# __init__.py
__all__ = ['os', 'sys', 're', 'urllib']
# a.py
from package import * #这时就会把注册在__init__.py文件中__all__列表中的模块和包导入到当前文件中来。
可以了解到,__init__.py主要控制包的导入行为。

通常__init__.py 文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的__init__.py文件。这样我们可以在__init__.py文件中批量导入我们所需要的模块,而不再需要一个一个的导入。
然后我们运行过你包里面的模块代码后会生成一个pyc文件,就是我上面说的编译后的文件,它的作用主要就是加快程序运行速度。

实例

我建一个简单的包,主要包含三个文件,setup.py和__init__ .py文件,以及我们的模块,大家可以看一下我的,虽然很low,主要也就是写给大家熟悉一下。
1.setup.py

from distutils.core import setup
setup(
    name = 'zf-first_package',
    version = '1.0.0',
    keywords = ('simple', 'test'),
    description = 'just a simple test',
    author = 'zf',
    author_email = '2063767947@qq.com',
    py_modules =['test1.fac_1']
)

2.init .py文件

import re
import urllib
import sys
import os
import random
__all__ = ['os', 'sys', 're', 'urllib','random']

3.模块文件

#import urllib.parse
import numpy as np
#import random
__all__ =['hello_1','my_add','p_1']#__all__变量控制那些功能可以用*导入
def my_add(x,y):
    return x+y
pipi = 3.0
p_1 =2
def hello_1():
    print("hello world!")
    
if __name__ =='__main__':
    print('This is my frist model')
    print('This i so badly package')
    print('__name__==',__name__)
def keyword_url(str1,encoding):
    """这个函数用来将中文转为网页对应的关键词编码,调用的是urllib包中的函数"""
    a = urllib.parse.quote(str1.encode(encoding))
    return a

def url_keyword(str1):
    '''
    解码作用,将网站的关键词编码转化为中文,也是调用urllib包中的一个函数
    '''
    a =urllib.parse.unquote(str1)
    return a 
  
def str1_fac(str1):
    '''字符串逆序输出'''
    b = str1[::-1]
    return b

def my_fac(num):
    '''求阶乘'''
    s = 1
    for i in range(1,num+1):
        s*=i
    return s
def loadData(fileName,ratio): 
    '''读取数据函数,输入为数据文件名和训练、测试切分比率,返回为list类型的训练数据集和测试数据集'''
    '''这个针对的是txt文档,fileName文件路径名,ratio文件划分比例'''
    trainingData=[]
    testData=[]
    with open(fileName) as txtData:
        lines=txtData.readlines()
        for line in lines:
            lineData=line.strip().split(',')    #去除空白和逗号“,”
            if random.random()<ratio:             #数据集分割比例
                trainingData.append(lineData)   #训练数据集列表
            else:
                testData.append(lineData)       #测试数据集列表
    return trainingData,testData

三引号括起来相当于是一个help()文档,就像我们平时说的那个help(),我们不知道一个函数的用法,help()就是起到这个作用。
最后模块和包就大致介绍到这里了,想了解更多的可以网上查一下资料。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值