一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
在 python 我们见过多种方式导入一个 module,大家可能没有意识到他们之间区别,可能在认识上还存在 confusing,今天和大家一起来看一看这些写法不同 import 其背后又有什么区别。
如果对 python 如何导入一个 module 可以参考之前的一篇文章 在 python 中,在导入 module 背后究竟发生了什么?
import numpy as np
import torch
from tqdm import tqdm
import matplotlib.pyplot as plt
首先我们会检测 sys.modules 中是否存在 socket 模块,如果已经加载就是定义 socket 对象指向存储 socket 对象的内存地址即可。如果 module 还没有加载,这需要对 module 文本进行编译执行来创建新的 module 对象,并且将 module 对象添加到 sys.modules 中。然后就是在全局命名空间内创建一个 symbol 或者变量指向创建好 module 对象内存地址。
在编译,还会将模块中包括方法、类等进行编译作为对象存储在内存中,在 socket 下的方法例如 gethostname 和 getnameinfo 都会被编译后存储在内存中,然后在 socket 持有这些引用的一个字典。
也就是我们在 import module 时候其 module 中包含方法例如 gethostname 和 getnameinfo 这些方法也作为 object 保存到内存中,然后socket 持有一个字典,键值为方法或者类名称,值指向存储该 object 的内存地址。
import socket as my_socket
我们也可以为 socket 在导入时起一个别名,这样好处便于区分,或者对一些比较常用库进行进化例如,import numpy as np 这样方便随后调用 numpy 可以通过给其别名 np 来访问 numpy 模块。
大家可能仅需要某一个 module 下的一个方法,然后通过如下语句导入 gethostname 方法。
from socket import gethostname
如果我们只想用 socket 的 gethostname 方法,这样做似乎节省了资源,直接加载使我们所需要 gethostname 方法,其实不然,即使这样做也会将 socket 整个对象及其下包含方法或者类也会事先加载到内存中,这样做和上面 import socket 开销是一样的,并没有节省内存。
from socket import *
这样做并不是什么明智选择,因为许多模块都存在相同名称的方法或者类,例如在 math 和 cmath 中就存在许多相同名称的方法或者类,我们利用别名方式来避免冲突。
from socket import gethostname as hostname