Python学习————模块

一、模块的介绍

在Python中,一个py文件就是一个模块,文件名为xxx.py模块名则是xxx,导入模块可以引用模块中已经写好的功能。如果把开发程序比喻成制造一台电脑,编写模块就像是在制造电脑的零部件,准备好零部件后,剩下的工作就是按照逻辑把它们组装到一起。

将程序模块化会使得程序的组织结构清晰,维护起来更加方便。比起直接开发一个完整的程序,单独开发一个小的模块也会更加简单,并且程序中的模块与电脑中的零部件稍微不同的是:程序中的模块可以被重复使用。所以总结下来,使用模块既保证了代码的重用性,又增强了程序的结构性和可维护性。另外除了自定义模块外,我们还可以导入使用内置或第三方模块提供的现成功能,这种“拿来主义”极大地提高了程序员的开发效率。

1.1 什么是模块

模块就是一系列功能的集合体,分为三大类

内置的模块

第三方模块

自定义模块

一个python文件本身就是一个模块,文件名m.py,模块名叫m

了解:模块分为四种形式

‘‘‘
1、使用python编写的.py文件
2、已被编译为共享库或DLL的c或c++扩展
3、把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
4、使用c编写并链接到python解释器的内置模块
‘‘‘

1.2 为何要有模块

  • 内置与第三方的模块拿来就用,无需定义,可以极大的提升自己的开发效率
  • 自定义模块:可以将程序的各部分功能提取出来放到一个模块中为大家共享使用,减少代码冗余,程序组织结构更加清晰

二、模块的使用

2.1 import语句

#文件名:foo.py
x=1
def get():
    print(x)
def change():
    global x
    x=0
class Foo:
    def func(self):
       print(‘from the func‘)

要想在另外一个py文件中引用foo.py中的功能,需要使用import foo,首次导入模块会做三件事:

1、执行源文件代码

2、产生一个新的名称空间用于存放源文件执行过程中产生的名字

3、在当前执行文件所在的名称空间中得到一个名字foo,该名字指向新创建的模块名称空间,若要引用模块名称空间中的名字,需要加上该前缀,如下

import foo #导入模块foo
a=foo.x #引用模块foo中变量x的值赋值给当前名称空间中的名字a
foo.get() #调用模块foo的get函数
foo.change() #调用模块foo中的change函数
obj=foo.Foo() #使用模块foo的类Foo来实例化,进一步可以执行obj.func()

加上foo.作为前缀就相当于指名道姓地说明要引用foo名称空间中的名字,所以肯定不会与当前执行文件所在名称空间中的名字相冲突,并且若当前执行文件的名称空间中存在x,执行foo.get()或foo.change()操作的都是源文件中的全局变量x。

执行py文件与导入py文件的区别

# 执行py文件时,产生对应py文件的名称空间,当该py文件的程序执行结束时名称空间才被回收
# 导入py文件时,py文件被当作模块引用,第一次导入模块时产生模块的名称空间,即导入的py文件的名称空间
# 当被导入py文件不再被其他文件所引用,即导入的py文件的引用计数为0时才会被回收
‘‘‘
1、当foo.py被运行时,__name__的值为"__main__"
2、当foo.py被当作模块导入时,__name__的值为"foo"
if __name__ == ‘__main__‘:
	print(‘文件被执行‘)
else:
	print(‘文件被导入‘)
‘‘‘

# import的优缺点
‘‘‘
import导入模块在使用时必须加前缀"模块."
优点:肯定不会与当前名称空间的名字冲突
缺点:加前缀显得麻烦
‘‘‘

2.2 from-import语句

from...import...与import语句基本一致,唯一不同的是:使用import foo导入模块后,

引用模块中的名字都需要加上foo.作为前缀,而使用from foo import x,get,change,

Foo则可以在当前执行文件中直接引用模块foo中的名字,如下

 from foo import x,get,change #将模块foo中的x和get导入到当前名称空间
a=x #直接使用模块foo中的x赋值给a
get() #直接执行foo中的get函数
change() #即便是当前有重名的x,修改的仍然是源文件中的x
    from...import...导入也发生了三件事
1、产生一个模块的名称空间
2、运行foo.py讲运行过程中产生的名字都丢到模块的名称空间
3、在当前名称空间拿到一个名字,该名字指向模块名称空间中的某一个内存地址
from foo import x # x=foo中1的内存地址
from foo import get
from foo import change

x=33333
print(x)
get()
change()
get()
print(x)
from foo import x # x=新的内存地址(0的内存地址)
print(x)

from...import...导入模块在使用时不用加前缀
‘‘‘
优点:代码更精简
缺点:容易与当前名称空间混淆
from foo import x # x=foo中1的内存地址
x=1111
‘‘‘

 一行导入多个名字(不推荐)
from foo import x,get,change
 *: 导入模块中的所有名字(大多数情况下不推荐使用,极容易与当前名称空间的名字混淆)
当你需要用到同一个模块中的多个名字时,
 此时可以使用*来进行代码精简,但也需要权衡,避免与当前名称空间的名字混淆

了解:__all__ 控制*代表的名字有哪些
from foo import *
print(x)
print(get)
print(change)

起别名
from foo import get as g
 *:导入模块中的所有名字
 name=‘egon‘
from foo import *
print(name)

另外from语句支持from foo import 语法,代表将foo中所有的名字都导入到当前位置

from foo import *
#把foo中所有的名字都导入到当前执行文件的名称空间中,在当前位置直接可以使用这些名字

a=x
get()
change()
obj=Foo()

2.3 循环导入问题

循环导入问题指的是在一个模块加载/导入的过程中导入另外一个模块,

而在另外一个模块中又返回来导入第一个模块中的名字,由于第一个模块

尚未加载完毕,所以引用失败、抛出异常,究其根源就是在python中,

同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,

即便是该模块尚未完全加载完毕也不会去重复执行内部代码

# m1.py
print(‘正在导入m1‘)
# from m2 import y
def f1():
    from m2 import y
    print(y)
x=‘m1‘

# m2.py
print(‘正在导入m2‘)
# from m1 import x
def f2():
    from m1 import x
    print(x)
y=‘m2‘

# run.py
import m1
m1.f1()

测试一

#1、执行run.py会抛出异常
正在导入m1
正在导入m2
Traceback (most recent call last):
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/aa.py", line 1, in <module>
    import m1
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module>
    from m2 import y
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m2.py", line 2, in <module>
    from m1 import x
ImportError: cannot import name ‘x‘

#2、分析
先执行run.py--->执行import m1,开始导入m1并运行其内部代码--->打印内容"正在导入m1"
--->执行from m2 import y 开始导入m2并运行其内部代码--->打印内容“正在导入m2”--->执行from m1 import x,由于m1已经被导入过了,所以不会重新导入,所以直接去m1中拿x,然而x此时并没有存在于m1中,所以报错

测试二

#1、执行文件不等于导入文件,比如执行m1.py不等于导入了m1
直接执行m1.py抛出异常
正在导入m1
正在导入m2
正在导入m1
Traceback (most recent call last):
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module>
    from m2 import y
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m2.py", line 2, in <module>
    from m1 import x
  File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa练习目录/m1.py", line 2, in <module>
    from m2 import y
ImportError: cannot import name ‘y‘

#2、分析
执行m1.py,打印“正在导入m1”,执行from m2 import y ,导入m2进而执行m2.py内部代码--->打印"正在导入m2",执行from m1 import x,此时m1是第一次被导入,执行m1.py并不等于导入了m1,于是开始导入m1并执行其内部代码--->打印"正在导入m1",执行from m1 import y,由于m1已经被导入过了,所以无需继续导入而直接问m2要y,然而y此时并没有存在于m2中所以报错

解决方案

# 方案一:导入语句放到最后,保证在导入时,所有名字都已经加载过
# 文件:m1.py
print(‘正在导入m1‘)

x=‘m1‘

from m2 import y

# 文件:m2.py
print(‘正在导入m2‘)
y=‘m2‘

from m1 import x

# 文件:run.py内容如下,执行该文件,可以正常使用
import m1
print(m1.x)
print(m1.y)

# 方案二:导入语句放到函数中,只有在调用函数时才会执行其内部代码
# 文件:m1.py
print(‘正在导入m1‘)

def f1():
    from m2 import y
    print(x,y)

x = ‘m1‘

# 文件:m2.py
print(‘正在导入m2‘)

def f2():
    from m1 import x
    print(x,y)

y = ‘m2‘

# 文件:run.py内容如下,执行该文件,可以正常使用
import m1

m1.f1()

注意:循环导入问题大多数情况是因为程序设计失误导致,上述解决方案也只是在烂设计之上的无奈之举,
在我们的程序中应该尽量避免出现循环/嵌套导入,如果多个模块确实都需要共享某些数据,
可以将共享的数据集中存放到某一个地方,然后进行导入

2.4 搜索模块的路径与优先级

模块其实分为四个通用类别,分别是:

1、使用纯Python代码编写的py文件

2、包含一系列模块的包

3、使用C编写并链接到Python解释器中的内置模块

4、使用C或C++编译的扩展模块

在导入一个模块时,如果该模块已加载到内存中,则直接引用,否则会优先查找内置模块,
然后按照从左到右的顺序依次检索sys.path中定义的路径,直到找模块对应的文件为止,
否则抛出异常。sys.path也被称为模块的搜索路径,它是一个列表类型
# 无论是import还是from...import在导入模块时都涉及到查找问题
# 优先级:
#	1、从内存找(内置模块)
#	2、按照sys.path中存放的文件的顺序依次查找要导入的模块
import sys
# 值为一个列表,存放了一系列的文件夹,
# 其中一个文件夹是当前执行文件所在的文件夹
print(sys.path) 

# 了解:sys.modules查看已经加载到内存中的模块
# 针对模块的优化方案
import sys
import foo
def func():
    import foo
func()
print(sys.modules)

# 找foo.py就把foo.py的文件夹临时添加到环境变量中
# 然后导入foo模块,程序结束append添加的环境变量就会被删除
sys.path.append(r‘文件夹路径‘)

2.5 区分py文件的两种用途

一个Python文件有两种用途,一种被当主程序/脚本执行,另一种被当模块导入,

为了区别同一个文件的不同用途,每个py文件都内置了__name__变量,

该变量在py文件被当做脚本执行时赋值为“main”,在py文件被当做模块导入时赋值为模块名

#foo.py
...
if __name__ == ‘__main__‘:
    print(‘文件被执行‘)
    # foo.py被当做脚本执行时运行的代码
else:
    print(‘文件被导入‘)
    # foo.py被当做模块导入时运行的代码

2.6 编写一个规范的模块

我们在编写py文件时,需要时刻提醒自己,该文件既是给自己用的,也有可能会被其他人使用,因而代码的可读性与易维护性显得十分重要,为此我们在编写一个模块时最好按照统一的规范去编写

"The module is used to..." #模块的文档描述

import sys #导入模块

x=1 #定义全局变量,如果非必须,则最好使用局部变量,这样可以提高代码的易维护性,并且可以节省内存提高性能

class Foo: #定义类,并写好类的注释
    ‘Class Foo is used to...‘
    pass

def test(): #定义函数,并写好函数的注释
    ‘Function test is used to…‘
    pass

if __name__ == ‘__main__‘: #主程序
    test() #在被当做脚本执行时,执行此处的代码

原文地址:https://www.cnblogs.com/x945669/p/12594014.html

时间: 2024-10-09 05:21:31

Python学习————模块的相关文章

Python学习模块说明

自学是个大坑!于是乎报名开始跟班学习,Python学习模块的内容为自己在学习过程中所做的笔记,内容大部分并不是原创,而是截取的各种比较好的笔记加自己归纳总结而成的,算作知识备忘吧.

python学习————模块subprocess

subprocess模块 该subprocess模块目标启动新的进程,并与之进行通信. 1.Call:执行程序,等待它完成,返回状态码. import subprocessret1 = subprocess.call(["cp ","-p"],shell=True)ret2 = subprocess.call(["cp","-p"],shell=False) Shell = True 允许shell是字符串形式. def ca

python学习-模块

模块基本知识 模块是实现某个功能的代码集合 模块分为三种: 内置模块:安装 python 时自带的模块 自定义模块:之前我们所写的所有函数也都可以被当做自定义模块 第三方模块:非安装 python 时自带的模块 1.模块的导入 Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入 导入模块的方法: import module #导入模块的所有内容 from module.xx import xx # 导入模块的某一个功能 from

Python学习---模块和包

模块: 一个模块就是一个包含Python代码的文件,一个文件就是一个模块 为什么使用模块 1.现在程序开发文件比较大,都放在一个文件中维护不方便,拆分成多个文件方便维护和管理 2.模块可以增加代码的重用率 3.模块可以当做命名空间 如何定义自己的模块 模块本身就是一个文件,所有py代码都可以在文件中直接书写,不过我们开发公用模块时,最好在模块中书写一下内容 变量 模块中的属性 函数 单独的功能 类 相似功能组合 模块测试代码 临时使用,被导入时不会执行 测试代码: 测试代码经常在开发模块时用于测

Python学习——模块的基本知识

# 定义# 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就# 是.py结尾的python文件(文件名:test.py,对应的模块名:test)# 包:用来从逻辑上组织模块的,本质就一个目录(必须带有一个_init.py文件) # 2.导入方法# import module name# import moduleI name,module2 name# from module alex import*-# from modulealex import ml,m

python学习——模块

#什么是模块? #已经写好的一组功能的集合 #别人写好的函数.变量.方法.放在一个文件里(这个文件可以被我们直接使用) # import os,re,sys,time #如何自己写一个模块 # 当创建.py文件,给他起个名字符合变量名命名规则的文件名,这个名字就是模块名 # 模块的导入 # import time #怎么使用time模块中的名字 # time.time() # import 的命名空间 #import的模块和当前文件在不同的命名空间中 #模块是否可以被重复导入 # 不可以 #怎么

python学习--创建模块

昨天做了python客户端和服务器端通信,并把接收到的信息写到数据库,因为对数据库进行操作是个经常调用的行为,所以我想把调用数据库的操作写成一个module来给其它python程序调用,所以将昨天的服务器端程序拆分为两个文件: 1.主程序python.py #!/usr/bin/env python import socket import json import connmysql s = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) h

Python inspect模块学习

今天发现Python inspect模块中一个有趣的功能, 可以让我们方便地检视Python库中的源代码, 知道模块具体是怎样实现的, 满足了像我这样有偷窥欲的人-.- 那就是inspect中的getsource 它的用法如下: 例如要检视Python的The Zen of Python 我们可以: In [1]: import inspect In [2]: import this The Zen of Python, by Tim Peters Beautiful is better tha

Python学习系列(六)(模块)

一,模块的基本介绍 1,import引入其他标准模块 标准库:Python标准安装包里的模块. 引入模块的几种方式: i)引入模块:import   moduleName ii)引入模块下的函数:from moduleName import function1,function2,-- iii)引入模块下的所有函数:from moduleName import * 使用模块里的函数的方法: moduleName.function(agrs) 示例: >>> import math >