文档章节

python入门(九)-- 模块与包

兴趣使然的程序员
 兴趣使然的程序员
发布于 2017/05/15 09:48
字数 2340
阅读 20
收藏 1

1、模块

1.1、模块与模块导入

模块是包括Python定义和声明的文件。文件名就是模块名加上.py后缀。模块的模块名(作为一个字符串)可以由全局变量_name_得到。

相对Java的.java文件,python中的.py文件更类似于C中的头文件:

# 一个只有两个函数的模块,命名为fibo.py
 

def fib(n):
    """打印斐波那契数组"""
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()


def fib2(n):
    """生成斐波那契数组"""
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result
# 在另外的文件中导入模块
import fibo

# 通过模块名直接访问函数
fibo.fib(5)
fib_ = fibo.fib2(5)

# 通过_name_全局属性查看模块名
fibo.__name__
# 还可以直接导入函数
from fibo import fib, fib2

# 就不需要通过模块名就可以直接调用
fib(50)
# 或者一次性导入所有
from fibo import *

注意:

  • 一次性导入所有模块并不是推荐的做法

除此之外需要注意的是:

  • 和Java运行jar文件类似,可以直接在python控制台直接运行.py文件:
python myproject.py <arguments>

         如果想要接收控制台传入的参数的参数的话,需要引入sys模块,例如:

# 导入sys模块
import sys

print("命令行参数如下:")
# 通过sys.argv获取参数列表
for i in sys.argv:
    print(i)

# 通过sys.path[0]获取文件路径
print('\n\nPython 路径为:',sys.path[0],'\n')
E:\pythonTest>python Test.py 1
命令行参数如下:
Test.py
1


Python 路径为: E:\pythonTest
  • 每个import语句只会被执行一次,如果被import的模块中有可执行的代码块(除了函数定义以外的代码块,一般用于初始化全局参数),这些代码块在import之前就会执行。如果不希望一些代码块被执行,可以用__name__(注意这里是两个下划线)进行控制,(当__name__为“main”时表明该模块自身在运行,否则是被引入)。 if __name__ == '__main__': 这条语句,它的作用是,只有在当前模块名为 __main__ 的时候(即作为脚本执行的时候)才会执行此 if 块内的语句。换句话说,当此文件以模块的形式导入到其它文件中时,if 块内的语句并不会执行。:
# 注意,只要当前模块被其他模块import了,下面的代码都会执行。和Java中的静态代码块有点类似。
print("程序在自身中运行,在其他文件中也运行")

# 这些代码只有在自身模块中运行。在其他模块中不运行
if __name__ == "__main__":
    print('程序在自身运行')
  • 除此之外还可以使用dir()函数找到模块内定义的所有名称,以一个字符串列表的形式返回:
import fibo

# 获取指定模块的可访问所有名称(全局变量和函数名)
print(dir(fibo))

# 如果不指定参数的话,dir()会返回当前模块可访问的所有名称
print(dir())

 

1.2、模块的搜索路径

在导入一个叫fibo的模块时,python解释器会先在当前目录中搜索名为fibo.py的文件。

如果没有找到的话,接着回到sys.path变量(如之前所提及,是当前能访问的路径的列表)中查找。sys.path变量的初始值(默认值)来自如下:

  • 输入脚本的目录(当前目录)
  • 环境变量PYTHONPATH表示的目录列表中搜索
  • Python默认安装路径中搜索

1.3、标准模块

Python带有一个标准模块库,这些模块内置于解释器中。和Java中不同,python的这些标准模块库多数依赖于底层平台,是为了给系统调用等操作系统原生访问提供接口。例如winreg模块只在Windows系统上才有。

1.3.1 Linux下的os 模块

os 模块提供了与操作系统相关的功能。你可以使用如下语句导入它:

>>> import os

getuid() 函数返回当前进程的有效用户 id。

>>> os.getuid()
500

getpid() 函数返回当前进程的 id。getppid() 返回父进程的 id。

>>> os.getpid()
16150
>>> os.getppid()
14847

uname() 函数返回识别操作系统的不同信息,在 Linux 中它返回的详细信息可以从 uname -a 命令得到。uname() 返回的对象是一个元组,(sysname, nodename, release, version, machine)

>>> os.uname()
('Linux', 'd80', '2.6.34.7-56.fc13.i686.PAE', '#1 SMP Wed Sep 15 03:27:15 UTC 2010', 'i686')

getcwd() 函数返回当前工作目录。chdir(path) 则是更改当前目录到 path。在例子中我们首先看到当前工作目录是 /home/shiyanlou,然后我们更改当前工作目录到 /Code 并再一次查看当前工作目录。

>>> os.getcwd()
'/home/shiyanlou'
>>> os.chdir('Code')
>>> os.getcwd()
'/home/shiyanlou/Code'

所以现在让我们使用 os 模块提供的另一个函数来创建一个自己的函数,它将列出给定目录下的所有文件和目录。

def view_dir(path='.'):
    """
    这个函数打印给定目录中的所有文件和目录
    :args path: 指定目录,默认为当前目录
    """
    names = os.listdir(path)
    names.sort()
    for name in names:
        print(name, end =' ')
    print()

使用例子中的 view_dir() 函数。

>>> view_dir('/')
.bashrc .dockerenv .profile bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

os 模块还有许多非常有用的函数,你可以在这里阅读相关内容。

1.4、“编译的”Python文件

Python是一种解释型语言,这意味着它和Java、C#等都不同(Java中会先将代码编译为.class文件然后交由JVM解释为机器码执行,C#类似),python文件是在运行的时候将程序翻译成机器语言。

但是为了实现“跨平台”和“加快加载模块的速度”,python会在__pycache__目录下以"module.version.pyc"(例如__pycache__/fibo.cpytion-33.pyc)的形式缓存每个模块编译后的版本

Python会自动通过检查源文件和编译版的修改日期来确定它是否过期并需要重新编译。

其余需要注意的是:

  • 对于直接从命令行加载的模块,Python永远会重新编译而不会从缓存中读取
  • 如果没有源模块(即只有编译版),python不会检查缓存(此时不检查也无所谓)。但是需要注意的是如果要支持没有源模块的发布,编译后的模块必须在源目录下
  • 编译缓存并不会使模块的运行速度变快,但是会使加载的速度变快

2、包

2.1、基本使用

和Java中的包的概念类似,python中的包同样用于更好的管理模块以及避免命名冲突。包的表示也和Java中的类似,例如A.B表示了名为A的包,和名为B的模块。

需要注意的和Java中不同的是,为了让Python把目录当做包目录中必须包含__init__.py文件。一般情况下,只需要一个空的__init__.py文件即可,当然也可以在__init__.py文件中执行包的初始化代码。

引用包和引用模块一样,也有三种方式:

# 每次都导入特定的模块
import package.fibo

# 每次调用的时候都需要些完整路径
package.fibo.fib(5)

# fibo.fin(5)或者fib(5)都会报错
# 导入指定模块
from package import fibo

# 这种方式就无需写包前缀
fibo.fib(5)
# 还可以导入指定的函数、类或变量
from package.fibo import fib

# 这种方式就无需写任何前缀
fib(5)

需要注意的是:

  • 使用import...的时候,import进来的必须是包或者模块
  • 使用from...import...的时候,可以import进来包、模块以及模块中定义的其他命名(函数、类或者变量),推荐使用form...import...。
  • 当import后面跟着的只到包时,并不会自动引入包下的所有模块。需要使用__all__属性指定想要导入的模块。

2.2、import * 与 __all__变量

在python中使用import * 时,如果没有定义 __all__ , from sound.effects import * 语句不会从 sound.effects 包中导入所有的子模块。

无论包中定义多少命名,只能确定的是导入了 sound.effects 包(可能会运行 __init__.py 中的初始化代码)以及包中定义的所有命名会随之导入。

如果希望使用import * 以节省敲打代码的工作量,可以在__init__.py文件中定义__all__变量,指定在使用import * 时导入的模块:

__all__ = ["echo", "surround", "reverse"]

虽然这样可以实现,但是实际工作中还是不推荐这种写法,推荐使用form import。

2.3、包内引用

在一个父包下,引用其他子包下的模块可以使用相对路径:

  • . 表示同一个包下
  • .. 表示上级目录下
  • ..pakage 表示上级目录的pakage包下

3、标准模块和第三方模块查找

Python 吸引人的一点是其有众多的模块可以使用,对于自带模块,可以看看 Python3 的官方文档,对于第三方模块,可以在 PyPI 上找找。很多时候你都能找到合适的包帮你优雅的完成部分工作。比如 argparse 模块帮你非常容易的编写用户友好的命令行接口。

© 著作权归作者所有

共有 人打赏支持
兴趣使然的程序员
粉丝 21
博文 112
码字总数 87412
作品 0
深圳
程序员
【Python入门只需20分钟】从安装到数据抓取、存储原来这么简单

  基于大众对Python的大肆吹捧和赞赏,作为一名Java从业人员,我本着批判与好奇的心态买了本python方面的书《毫无障碍学Python》。仅仅看了书前面一小部分的我......决定做一名python的脑残...

旺旺笔记
08/23
0
0
Python基础总结成千行代码,让Python入门更简单!

只要学会这千行代码,不管你是零基础还是弱基础或是没有接触过编程,都可以快速入门Python!当时我就不信邪啊,等我看完之后,即使作为一个Python老鸟了,还是领会到了很多教授他的独特见解!...

糖宝lsh
09/10
0
0
这可能是最好玩的python GUI入门实例!

简单的说,GUI编程就是给程序加上图形化界面. python的脚本开发简单,有时候只需几行代码就能实现丰富的功能,而且python本身是跨平台的,所以深受程序员的喜爱. 如果给程序加一个图形化界面,那么...

zhaoolee
2017/09/16
0
0
python 入门笔记 (模块)

一、模块基础 1、模块 自我包含,且有组织的代码片段就是模块 模块是Pyhon最高级别的程序组织单元,它将程序代码和数据封装起来以便重用。实际的角度,模块往往对应Python程序文件。 每个文件...

QEfarmer
2015/04/03
0
1
Python入门到进阶,这本书有什么不同?

人们常说Python语言简单,编写简单程序时好像也确实如此。但实际上Python绝不简单,它也是一种很复杂的语言,其功能特征非常丰富,能支持多种编程风格,在几乎所有方面都能深度定制。要想用好...

异步社区
08/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Univalsal_ImageLoader源码结构与创建者模式 初步小结

最近在回归看Univalsal_ImageLoader源码,本想自己也实现试试写一个,看源码是为了学习看能否使用,助于自己可以写出有自己逻辑结构的代码。 首先我们初始化ImageLoader的配置初始化的时候,...

DannyCoder
27分钟前
0
0
计算卷积神经网络浮点数运算量

前言 本文主要是介绍了,给定一个卷积神经网络的配置之后,如何大概估算它的浮点数运算量。 相关代码:CalFlops,基于MXNet框架的 Scala 接口实现的一个计算MXNet网络模型运算量的demo。 正文...

Ldpe2G
今天
1
0
Sql语言与MySql数据库

1. 数据库简介 1. 数据库,就是存储数据的仓库,只能通过sql语言来访问,数据库也是一个文件系统。通常,MySQL、Oracle等数据库,也被称为关系型数据库,其保存的不仅仅只是数据,还包括数据...

江左煤郎
今天
1
0
IDEA 取消自动import .*

打开设置 > Editor > Code Style > Java > Scheme Default > Imports ① 将 Class count to use import with "*" 改为 99 (导入同一个包的类超过这个数值自动变为 * ) ② 将 Names count ......

乔老哥
今天
3
0
PostGIS学习笔记(开篇)

PostGIS事实上算是笔者开始写博客的第一篇内容。而事实上那篇博文的内容并不丰富,笔者对PostGIS的了解仍然不多,然而17年在OSGeo课程学习时对PostGIS又有了进一步了解,并逐步发现它的强大。...

胖胖雕
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部