python中import re_彻底搞懂Python 中的 import 与 from import

2023-11-11

对不少 Python 初学者来说,Python 导入其他模块的方式让他们很难理解。什么时候用import xxx?什么时候用from xxx import yyy?什么时候用from xxx.yyy import zzz?什么时候用from xxx import *?

这篇文章,我们来彻底搞懂这个问题。

系统自带的模块

以正则表达式模块为例,我们经常这样写代码:

1

2

3

4

import re

target = 'abc1234xyz'

re.search('(\d+)', target)

但有时候,你可能会看到某些人这样写代码:

1

2

3

from re import search

target = 'abc1234xyz'

search('(\d+)', target)

那么这两种导入方式有什么区别呢?

我们分别使用type函数来看看他们的类型:

1

2

3

4

5

6

>>> import re

>>> type(re)

>>> from re import search

>>> type(search)

如下图所示:

2019-12-28-13-30-59.png

可以看到,直接使用import re导入的re它是一个module类,也就是模块。我们把它成为正则表达式模块。而当我们from re import search时,这个search是一个function类,我们称呼它为search 函数。

一个模块里面可以包含多个函数。

如果在你的代码里面,你已经确定只使用search函数,不会再使用正则表达式里面的其他函数了,那么你使用两种方法都可以,没什么区别。

但是,如果你要使用正则表达式下面的多个函数,或者是一些常量,那么用第一种方案会更加简洁清晰。

例如:

1

2

3

4

import re

re.search('c(.*?)x', flags=re.S)

re.sub('[a-zA-Z0-9]', '***', target, flags=re.I)

在这个例子中,你分别使用了re.search,re.sub,re.S和re.I。后两者是常量,用于忽略换行符和大小写。

但是,如果你使用from re import search, sub, S, I来写代码,那么代码就会变成这样:

1

2

3

4

import re

search('c(.*?)x', flags=S)

sub('[a-zA-Z0-9]', '***', target, flags=I)

看起来虽然简洁了,但是,一旦你的代码行数多了以后,你很容易忘记S和I这两个变量是什么东西。而且我们自己定义的函数,也很有可能取名为sub或者search,从而覆盖正则表达式模块下面的这两个同名函数。这就会导致很多难以觉察的潜在 bug。

再举一个例子。Python 的 datetime模块,我们可以直接import datetime,此时我们导入的是一个datetime模块,如下图所示:

2019-12-28-13-43-21.png

但是如果你写为from datetime import datetime,那么你导入的datetime是一个type类:

2019-12-28-13-45-07.png

因为这种方式导入的datetime,它就是Python 中的一种类型,用于表示包含日期和时间的数据。

这两种导入方式导入的datetime,虽然名字一样,但是他们的意义完全不一样,请大家观察下面两种写法:

1

2

3

4

import datetime

now = datetime.datetime.now()

one_hour_ago = now - datetime.timedelta(hours=1)

1

2

3

from datetime import datetime, timedelta

now = datetime.now()

one_hour_ago = now - timedelta(hours=1)

第二种写法看似简单,但实则改动起来却更为麻烦。例如我还需要增加一个变量today用于记录今日的日期。

对于第一段代码,我们只需要增加一行即可:

1

today = datetime.date.today()

但对于第二行来说,我们需要首先修改导入部分的代码:

1

from datetime import datetime, timedelta, date

然后才能改代码:today = date.today()

这样一来你就要修改两个地方,反倒增加了负担。

第三方库

在使用某些第三方库的代码里面,我们会看到类似这样的写法:

1

2

3

from lxml.html import fromstring

selector = fromstring(HTML)

但是我们还可以写为:

1

2

3

from lxml import html

selector = html.fromstring(HTML)

但是,下面这种写法会导致报错:

1

2

import lxml

selector = lxml.html.fromstring(HTML)

那么这里的lxml.html又是什么东西呢?

这种情况多常见于一些特别大型的第三方库中,这种库能处理多种类型的数据。例如lxml它既能处理xml的数据,又能处理html的数据,于是这种库会划分子模块,lxml.html模块专门负责html相关的数据。

自己来实现多种导入方法

我们现在自己来写代码,实现这多种导入方法。

我们创建一个文件夹DocParser,在里面分别创建两个文件main.py和util.py,他们的内容如下:

util.py文件:

1

2

def write():

print('write 函数被调用!')

main.py文件:

1

2

3

import util

util.write()

运行效果如下图所示:

2019-12-28-14-06-29.png

现在我们把main.py的导入方式修改一下:

1

2

3

from util import write

write()

依然正常运行,如下图所示

2019-12-28-14-07-21.png

当两个文件在同一个文件夹下面,并且该文件夹里面没有init.py 文件时,两种导入方式等价。

现在,我们来创建一个文件夹microsoft,里面再添加一个文件parse.py:

1

2

def read():

print('我是 microsoft 文件夹下面的 parse.py 中的 read函数')

如下图所示:

2019-12-28-14-11-17.png

此时我们在 main.py中对它进行调用:

1

2

3

from microsoft import parse

parse.read()

运行效果如下图所示:

2019-12-28-14-12-17.png

我们也可以用另一种方法:

1

2

3

from microsoft.parse import read

read()

运行效果如下图所示:

2019-12-28-14-13-17.png

但是,你不能直接导入microsoft,如下图所示:

2019-12-28-14-15-35.png

你只能导入一个模块或者导入一个函数或者类,你不能导入一个文件夹

无论你使用的是import xxx还是from xxx.yyy.zzz.www import qqq,你导入进来的东西,要不就是一个模块(对应到.py 文件的文件名),或者是某个.py 文件中的函数名、类名、变量名。

无论是import xxx还是from xxx import yyy,你导入进来的都不能是一个文件夹的名字。

可能有这样一种情况,就是某个函数名与文件的名字相同,例如:

在 microsoft文件夹里面有一个microsoft.py文件,这个文件里面有一个函数叫做microsoft,那么你的代码可以写为:

1

2

from microsoft import microsoft`

microsoft.microsoft()

但请注意分辨,这里你导入的还是模块,只不过microsoft.py文件名与它所在的文件夹名恰好相同而已。

总结

无论是使用import还是from import,第一个要求是代码能够正常运行,其次,根据代码维护性,团队编码风格来确定选择哪一种方案。

如果我们只会使用到某个模块下面的一个函数(或者常量、类)并且名字不会产生混淆,可识别性高,那么from 模块名 import 函数名这没有什么问题。

如果我们会用到一个模块下面的多个函数,或者是我们将要使用的函数名、常量名、类名可能会让人产生混淆(例如 re.S、re.I),那么这种情况下,import 模块名然后再 模块名.xxx来调用会让代码更加清晰,更好维护。

但无论什么情况下,都禁止使用from xxx import *这种写法,它会给你带来无穷无尽的噩梦。

未完待续

在明天的文章中,我们来讲讲还有一种写法from . import xxx,以及当文件夹中存在__init__.py时,导入方式又有什么变化。

转自:微信公众号:未闻code

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python中import re_彻底搞懂Python 中的 import 与 from import 的相关文章

  • Springboot1.5.9集成Redis(单实例与分片集群)

    springboot集成redis只需要看懂RedisAutoConfiguration类即可 惯例先上pom start
  • FastDFS,Redis,Solr,ActiveMQ核心技术整合六

    02 商品分类选择 分析 前端js 03 商品分类选择 分析 数据库 JJTree渲染过程解析 parent id为0就是父节点 is parent为1说明下面有子节点 state1正常2删除 tree组件有ztree 异步控件树每个节点都
  • PyG-GAT-Cora(在Cora数据集上应用GAT做节点分类)

    文章目录 model py main py 参数设置 运行图 model py import torch nn as nn from torch geometric nn import GATConv import torch nn fun
  • 《基于 Vue 组件库 的 Webpack5 配置》5.js代码混淆

    使用 插件 webpack obfuscator 需要安装 npm install save dev javascript obfuscator webpack obfuscator package json 的配置如下 const Web
  • TextView设置字重

  • 类中找不到main方法请将main方法定义为public static void main. 否则 JavaFX 应用程序类必须扩展javafx.application.Application

    使用elcipise编写java程序时遇到这样的错误 错误在类中找不到main方法 请将main方法定义为 public static void main String args 否则 JavaFX 应用程序类必须扩展javafx appl
  • 浮点运算量FLOPs与算力单位FLOPS

    概念 FLOPS 注意全大写 是floating point operations per second的缩写 意指每秒浮点运算次数 理解为计算速度 是一个衡量硬件性能的指标 FLOPs 注意s小写 是floating point oper
  • react组件封装input框的防抖处理

    防抖 防抖就是指触发事件后在 n 秒内函数只能执行一次 如果在 n 秒内又触发了事件 则会重新计算函数执行时间 项目中有些input框需要做防抖处理 防止每次输入都要发起请求或者做判断 也就是减少触发频率 以便提高性能或者说避免资源浪费 防
  • 使用Python,OpenCV截取图片ROI

    使用Python OpenCV截取图片ROI 1 效果图 2 步骤 2 1 环境配置 2 2 原理 3 源码 参考 这篇博客将介绍如何使用Python OpenCV截取图片ROI Regions Of Interests 即我们感兴趣的部分
  • 做機器人一定很貴嗎?用塑膠也能做出捏起小鋼珠的機器手臂

    本文转载至 http buzzorange com techorange 2014 12 16 robot 人體的手部運動到底有多精密呢 看看機器人的研發過程就知道了 大部份的工程師都會坦承 模擬人類的手部動作 是研發機器人過程中最大的關卡
  • 内网怎么使用https

    内网环境下面需要用到https 通过浏览器调起相机的功能 一般情况下我们使用openssl证书生成即可 有个问题是生成的证书 通过nginx配置以后 在客户端谷歌浏览器chrome访问的时候会有个不安全的提示 这里使用mkcert进行处理
  • typedef的用法小总结

    首先是typedef历史遗留问题 经常看到很多人写结构体就写 typedef struct A int a int b A A b 我就一直很纳闷 为什么不直接写 A b呢 昨天查资料才知道 原来这个是因为c语言遗留下来的 在C语言中 结构
  • Notepad++配合Finger Text提高Verilog编码效率

    文章目录 简介 安装方法 使用方法 配置文件的获取 简介 做FPGA开发的一般都不会选择IDE环境自带的编辑器 一是因为界面不够美观 二是自动补全功能不够完善 而我经常使用的是Notepad 支持Verilog语法高亮和最基本的关键字补全
  • 单细胞测序基础知识

    构建文库 上机测序 根据不同的荧光检测不同的碱基 质量控制 质控QC 去除低质量的序列 表达定量 统计reads数 进而得到表达矩阵 标准化 让所有样本处在同一起跑线上 主成分分析PCA 图中每个点都代表一个样本 不同颜色表示不同类别 在绿
  • 华为太长脸了,扔出“3张王炸”!再次颠覆互联网行业

    8月29日 在没有任何预告 任何发布会的情况下 华为扔出一张 王炸 华为新手机Mate60pro开售 9月8日 华为废话不多说 再次扔出 王炸 牌 Mate60 Pro MateX5开启预订 一经开抢 卖到断货 就在刚刚 华为AITO问界新
  • .bat批处理命令常用操作

    转载自 https www cnblogs com aspirant p 7233893 html 感谢博主的分享 转载过来学习一下 Bat命令学习 一 基础语法 1 批处理文件是一个 bat 结尾的文本文件 这个文件的每一行都是一条DOS
  • 【解决问题】使用pip安装模块后,VS Code无法加载

    easydict 显示安装成功 但在导入包时显示红色波浪线 Import easydict could not be resolved 解决办法 设置 gt 搜索 python autoComplete extraPaths gt 将包的地
  • YOLOV5摔倒检测识别

    一 摔倒检测的实际意义 摔倒检测是一种人工智能技术 可用于监测和识别可能发生在老年人 幼儿 体育运动员等群体中的摔倒事件 在实际应用中 摔倒检测技术可以帮助本文 及时发现摔倒事件 通过监测设备和传感器 及时发现摔倒事件 可以避免因为无人发现
  • 【K8S】之 下载Kubeadm、node组件和命令行工具

    文章目录 一 安装kubeadm kubelet和kubectl 1 添加kubernets apt源公钥文件 2 加入kubernetes的官方源 3 安装工具 二 核心组件镜像下载 1 先查看kubeadm版本 2 再根据查看其所需镜像

随机推荐

  • org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates

    今天在整合swagger的时候遇到了这个问题 解决了一天终于搞定了 分享出来希望大家少走弯路 报错的具体信息如下 org springframework beans factory BeanDefinitionStoreException
  • (模板)米勒罗宾素数测试

    18位素数 154590409516822759 19位素数 2305843009213693951 梅森素数 19位素数 4384957924686954497 LL prime 6 2 3 5 233 331 LL qmul LL x
  • splunk安装在 windows、linux and Mc OS

    Install Splunk Enterprise for windows linux and Mc OS
  • Python 不用selenium 带你高效爬取京东商品评论

    文章目录 一 项目说明 1 项目背景 2 项目环境 二 项目实施 1 项目分析 2 代码实现 导入模块和定义常量 爬取评论主体函数 主函数 三 项目分析和说明 1 运行测试 2 改进分析 3 其他说明 一 项目说明 1 项目背景 一天 一朋
  • vuex的实现原理?(vue2)

    通常我们使用vuex 都是通过下载vuex插件 自己创建一个store目录 在里面创建一个js文件 在文件中引入vuex vue use我们的vuex从而通过实例化一个vuex 定义五大核心从而实现一个基本的vuex 那我们如何不下载插件
  • 基于STM32F407ZET6的环境温湿度监控系统(粤嵌GEC-M4)

    注意使用事项 开发板如下 由于外部晶振是8M 需要修改setup和stm32f4头文件的晶振值 操作如下 system stm32f4xx c的254行 define PLL M 8 stm32f4xx h的127行 define HSE
  • 算法笔记:Frechet距离度量

    曲线之间相似性的度量 它考虑了沿曲线的点的位置和顺序 1 概念 1 1 直观理解 主人走路径A 狗走路径B 他们有不同的配速方案 主人和狗各自走完这两条路径过程中所需要的最短狗绳长度 在某一种配速下需要的狗绳长度 但其他配速下需要的狗绳长度
  • Dictionary字典的用法及用途原理

    Dictionary 实例化Dictionary private Dictionary
  • wx原生微信小程序入门常用总结

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 定义值和修改值 1 定义值 2 修改值 1 代码 2 代码说明 3 注意点 二 点击事件 三 微信小程序的数据缓存 以setStorage为例使用 0 s
  • java linux class_Linux 下运行 class 文件

    1 基本命令 java cp searchDir classFile cp searchDir 指定从该目录搜索 class 文件 classFile 类路径 不包含 class 后缀 2 没有包结构的class文件 2 1 文件所在目录结
  • mybatis-plus中的条件构造器wrapper

    接口方法的参数中 会出现各种 Wrapper 比如 queryWrapper updateWrapper 等 Wrapper 的作用就是用于定义各种各样的条件 where 所以不管是查询 更新 删除都会用到 Wrapper 如 QueryW
  • el-date-picker怎样获取选择的时间范围值并判断是否大于7天

    场景 SpringBoot Vue Echarts实现选择时间范围内数据加载显示柱状图 SpringBoot Vue Echarts实现选择时间范围内数据加载显示柱状图 BADAO LIUMANG QIZHI的博客 CSDN博客 在上面需要
  • Linux网络编程:基础知识入门学习笔记汇总

    学习Linux的网络编程原则上基于 Linux的系统编程 和 Linux基础的Shell编程 第十章 除此之外还包含了计算机网络的知识 Linux基础shell编程 gt Linux 系统编程 gt Linux 网络编程 来源 黑马程序员
  • Hostmonitor邮件告警

    Hostmonitor可以通过邮件告警 打开Hostmonitor应用 1 点击Options 2 选择Mailer settings 3 Address输入框中填写网易邮箱的SMTP服务器地址 Port 输入框输入网易邮箱服务器端口 Au
  • 报`Uncaught (in promise)`错误解决办法

    使用了promise 但是在使用的过程中报Uncaught in promise 错误 第一次遇到这种错误 所以在此记录下 方便以后解决问题 getImage function url return new Promise resolve
  • getnameinfo failed

    在虚拟机vmware中用netstat 查看网络状态出现一行 getnameinfo failed 可能的一个原因 虚拟机使用NAT方式链接网络 解决方法 使用桥接方式即可
  • 【从零开始学c++】——类与对象(二)

    类与对象 1 构造函数 1 1构造函数的定义 1 2构造函数的特性 2 析构函数 2 1概念 2 2 特性 3 拷贝构造函数 3 1 概念 3 2 拷贝构造函数的特性 4 赋值运算符的重载 4 1 概念 4 2 实现日期类的运算符 4 2
  • 【Java基础知识 14】java动态代理原理

    Java学习路线思维导图 Java学习路线总结 思维导图篇 Java学习路线配套文章 搬砖工逆袭Java架构师 哪吒社区入口 哪吒社区 简介 Java领域优质创作者 CSDN哪吒公众号作者 Java架构师奋斗者 扫描主页左侧二维码 加入群聊
  • cumsum() R函数:用于产生随机变量的累积和

    gt 1 4 1 1 2 3 4 gt cumsum 1 4 1 1 3 6 10 函数介绍 Returns a vector whose elements are the cumulative sums cumsum 函数 Cumulat
  • python中import re_彻底搞懂Python 中的 import 与 from import

    对不少 Python 初学者来说 Python 导入其他模块的方式让他们很难理解 什么时候用import xxx 什么时候用from xxx import yyy 什么时候用from xxx yyy import zzz 什么时候用from