您现在的位置是:网站首页> 编程资料编程资料

Python基础之模块详解_python_

2023-05-26 398人已围观

简介 Python基础之模块详解_python_

一、模块

模块可以看成是一堆函数的集合体。

一个py文件内部就可以放一堆函数,因此一个py文件就可以看成一个模块。

如果这个py文件的文件名为module.py,模块名则是module

1、模块的四种形式

在Python中,总共有以下四种形式的模块:

  • 自定义模块:如果你自己写一个py文件,在文件内写入一堆函数,则它被称为自定义模块,即使用python编写的.py文件
  • 第三方模块:已被编译为共享库或DLL的C或C++扩展 ,如requests
  • 内置模块:使用C编写并链接到python解释器的内置模块 ,如time
  • 包(文件夹):把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)

2、为什么要用模块?

  • 用第三方或者内置的模块是一种拿来主义,可以极大地提升开发效率。
  • 自定义模块,将我们自己程序中用到的公共功能,写入一个python文件,然后程序的各部分组件可以通过导入的方式来引用自定义模块的功能。

二、如何用模块

一般我们使用import和from...import...导入模块。

以下述spam.py内的文件代码为例。

# spam.py print('from the spam.py') money = 1000 def read1(): print('spam模块:', money) def read2(): print('spam模块') read1() def change(): global money money = 0

1、import 模块名

语法如下:

import module1[, module2[,... moduleN]

import导入的模块,访问需要加前缀。

import首次导入模块发生了3件事:

  • 以模块为准创造一个模块的名称空间
  • 执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
  • 在当前执行文件中拿到一个模块名

注意:模块的重复导入会直接引用之前创造好的结果,不会重复执行模块的文件。

# run.py import spam # from the spam.py import spam money = 111111 spam.read1() # 'spam模块:1000' spam.change() print(spam.money) # 0 print(money) # 111111

导入重命名:smt变量指向span模块的名称空间

# run.py import spam as sm money = 111111 sm.money sm.read1() # 'spam模块:1000' sm.read2 sm.change() print(money) # 1000

导入多个模块

import spam, time, os # 推荐使用下述方式 import spam import time import os

2、from 模块名 import 具体的函数

语法如下:

from modname import name1[, name2[, ... nameN]]

这个声明不会把整个模块导入到当前的命名空间中,它只会将模块里的一个或多个函数引入进来。

from...import...导入的模块,访问不需要加前缀。

from...import...首次导入模块发生了3件事:

  • 以模块为准创造一个模块的名称空间
  • 执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
  • 在当前执行文件的名称空间中拿到一个名字,该名字直接指向模块中的某一个名字,意味着可以不用加任何前缀而直接使用
  • 优点:不用加前缀,代码更加精简
  • 缺点:容易与当前执行文件中名称空间中的名字冲突
# run.py from spam import money from spam import money,read1 money = 10 print(money) # 10

rom … import * 语句:导入文件内所有的功能:

# spam.py __all__ = ['money', 'read1'] # 只允许导入'money'和'read1' # run.py from spam import * # 导入spam.py内的所有功能,但会受限制于__all__ money = 111111 read1() # 'spam模块:1000' change() read1() # 'spam模块:0' print(money) # 111111

3、循环导入

以下情况会出现循环导入:

# m1.py print('from m1.py') from m2 import x y = 'm1' # m2.py print('from m2.py') from m1 import y x = 'm2'

可以使用函数定义阶段只识别语法的特性解决循环导入的问题,或从本质上解决循环导入的问题,但是最好的解决方法是不要出现循环导入。

方案一:

# m1.py print('from m1.py') def func1(): from m2 import x print(x) y = 'm1' # m2.py print('from m2.py') def func1(): from m1 import y print(y) x = 'm2'

方案二:

5、# m1.py print('from m1.py') y = 'm1' from m2 import x # m2.py print('from m2.py') x = 'm2' from m1 import y

4、dir() 函数

内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:

dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount', 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions']

如果没有给定参数,那么 dir() 函数会罗列出当前定义的所有名称:

a = [1, 2, 3, 4, 5] import fibo fib = fibo.fib print(dir()) # 得到一个当前模块中定义的属性列表 # ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys'] b = 5 # 建立一个新的变量 'a' print(dir()) # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b'] del b # 删除变量名a print(dir()) # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a']

三、模块搜索路径

1、导入模块时查找模块的顺序

1、先从内存中已经导入的模块中寻找

如果我们在运行run.py文件的时候,快速删除mmm.py文件,我们会发现文件会继续运行,而不会报错,因为mmm已经被导入内存当中。如果我们再一次运行run.py时会报错,因为mmm.py已经被删除了。

# test.py import m1 # 从m1.py文件中导入的,然后会生成m1模块的名称空间 import time # 删除m1.py文件,m1模块的名称空间仍然存在 time.sleep(10) import m1 # 不报错,一定不是从文件中获取了m1模块,而是从内存中获取的

2、内置的模块

验证先从内置中找,不会先找自定义的time.py文件。

# time.py print('from time.py') # run.py import time print(time) #

3、环境变量sys.path中找(强调:sys.path的第一个值是当前执行文件的所在的文件夹)

import sys for n in sys.path: print(n) # C:\PycharmProjects\untitled\venv\Scripts\python.exe C:/PycharmProjects/untitled/hello.py # C:\PycharmProjects\untitled # C:\PycharmProjects\untitled # C:\Python\Python38\python38.zip # C:\Python\Python38\DLLs # C:\Python\Python38\lib # C:\Python\Python38 # C:\PycharmProjects\untitled\venv # C:\PycharmProjects\untitled\venv\lib\site-packages

如果mmm.py在C:\PycharmProjects\untitled\day16路径下,而执行文件路径为C:\PycharmProjects\untitled,如果普通导入一定会报错,我们可以把C:\PycharmProjects\untitled\day16添加到环境变量sys.path中,防止报错。

# run.py import sys sys.path.append(r'C:\PycharmProjects\untitled\day16') print(sys.path) import mmm mmm.f1()

2、搜索路径以执行文件为准

假设我们有如下目录结构的文件,文件内代码分别是:

而hello和spam.py不是同目录下的,因此run.py的环境变量无法直接找到m2,需要从文件夹导入

提示: 本文由整理自网络,如有侵权请联系本站删除!
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!

-六神源码网