15.Python中将函数存储在模块中:五种导入方式

Python 中将函数存储在模块中:五种导入方式

本文档面向零基础新手,详细讲解什么是模块如何把函数写在模块里,以及 Python 中五种常用的导入方式的写法、区别和注意点,并配有大量示例。


第一部分:什么是模块?为什么要把函数放在模块里?

一、模块的概念

模块(module) 就是一个.py 结尾的 Python 文件。这个文件里可以写变量、函数、类等。别的 Python 程序可以通过 import 把这个文件“引入”进来,使用里面定义好的函数或变量。

可以简单记:

  • 模块 = 一个 .py 文件
  • 把函数写在模块里 = 把函数写在这个 .py 文件里,以后在别的文件里“导入”再调用

好处:

  • 代码分开:主程序只写“做什么”,具体实现放在模块里,主程序更短、更清晰
  • 复用:多个程序可以共用同一份模块,不用复制粘贴
  • 维护:改函数逻辑时只改模块文件,所有导入它的程序都会用到新逻辑

二、先准备一个“模块文件”示例

后面所有“导入方式”的示例,都会用到下面这个模块。请你先在同一目录下新建一个文件,例如:my_utils.py(名字可以自取,但不要用数字开头,不要有空格),内容如下:

# my_utils.py —— 这是一个“模块”,里面放了几个函数

def greet(name):
    """和 name 打招呼"""
    return "你好," + name

def add(a, b):
    """求 a + b"""
    return a + b

def multiply(a, b):
    """求 a * b"""
    return a * b

PI = 3.14159   # 模块里也可以放变量,供别人导入使用

这个文件就是我们的自定义模块,里面有 3 个函数和 1 个变量。下面在另一个文件(例如 main.py,和 my_utils.py 放在同一文件夹里)里演示五种导入方式。

重要: 默认情况下,Python 只会从当前运行脚本所在目录以及标准库路径里找模块。所以练习时请把“调用方”脚本(如 main.py)和模块文件(如 my_utils.py)放在同一目录下。


第二部分:五种导入方式详解

三、方式一:import 模块名(导入整个模块)

写法:

import 模块名

含义: 把整个模块“搬进来”,使用其中的函数或变量时,必须写成 模块名.函数名模块名.变量名

示例(在 main.py 中):

import my_utils

print(my_utils.greet("小明"))       # 你好,小明
print(my_utils.add(3, 5))          # 8
print(my_utils.multiply(2, 4))      # 8
print(my_utils.PI)                 # 3.14159

特点:

  • 优点:一眼就能看出某个函数或变量来自哪个模块,不会和当前文件里的名字冲突
  • 缺点:每次调用都要写“模块名.”,稍长一点

注意: 这里的“模块名”是文件名去掉 .py。例如文件叫 my_utils.py,就写 import my_utils,不能写 import my_utils.py


四、方式二:from 模块名 import 函数名(导入指定的函数或变量)

写法:

from 模块名 import 函数名或变量名

可以写多行,也可以在一行里用逗号分隔导入多个名字:

from 模块名 import 函数名1, 函数名2, 变量名

含义: 只把该模块里指定的函数(或变量)“拿进来”,使用时直接写函数名,不需要再加“模块名.”。

示例(在 main.py 中):

from my_utils import greet, add

print(greet("小红"))   # 你好,小红(直接用 greet,不用写 my_utils.greet)
print(add(10, 20))     # 30
# print(multiply(2, 3))  # 若没导入 multiply,这里会报错:NameError

再导入变量:

from my_utils import greet, add, PI
print(PI)   # 3.14159

特点:

  • 优点:调用时简短,直接写函数名
  • 缺点:如果当前文件里也定义了同名的函数或变量,会覆盖导入的名字,容易搞混;读代码时有时看不出这个名字来自哪个模块

五、方式三:from 模块名 import 函数名 as 别名(导入并起别名)

写法:

from 模块名 import 函数名 as 别名

含义: 导入该函数(或变量),但在当前文件里用另一个名字来用,避免名字太长或和本文件里的名字冲突。

示例(在 main.py 中):

from my_utils import greet as say_hi
from my_utils import multiply as mul

print(say_hi("小刚"))   # 你好,小刚(用别名 say_hi 调用)
print(mul(3, 4))       # 12(用别名 mul 调用,比 multiply 短)

常见用途:

  • 模块名或函数名太长,用短一点的别名
  • 当前文件里已有同名函数,用别名区分“是模块里的那个”

六、方式四:import 模块名 as 别名(导入整个模块并起别名)

写法:

import 模块名 as 别名

含义: 导入整个模块,但在当前文件里用别名来引用它。调用时写 别名.函数名别名.变量名

示例(在 main.py 中):

import my_utils as utils

print(utils.greet("小明"))    # 你好,小明
print(utils.add(1, 2))        # 3
print(utils.PI)               # 3.14159

常见用途:

  • 模块名很长时,用短别名,例如:import numpy as npimport matplotlib.pyplot as plt

七、方式五:from 模块名 import *(导入模块中的“所有”公共名字)

写法:

from 模块名 import *

含义: 把该模块里所有对外公开的名字(一般是不以下划线开头的)都导入到当前文件,使用时直接写函数名或变量名,不需要“模块名.”。

示例(在 main.py 中):

from my_utils import *

print(greet("小明"))     # 你好,小明
print(add(2, 3))         # 5
print(multiply(2, 3))    # 6
print(PI)                # 3.14159

为什么一般不推荐:

  1. 可读性差:看代码时很难一眼看出 greetadd 来自哪个模块,项目一大就容易乱
  2. 容易覆盖:模块里名字很多时,很容易和当前文件里的变量或函数同名,导致被覆盖或难以排查 bug
  3. 规范建议:PEP 8 等风格指南建议尽量避免 import *

什么时候勉强可以用: 只在很小的、自己写的练习脚本里图方便时用一下;正式项目或和别人协作时,更推荐用方式一方式二


第三部分:五种方式对比小结

八、对照表

导入方式 写法示例 调用方式 适用场景
方式一 import my_utils my_utils.greet("小明") 需要明确标出来源,避免重名
方式二 from my_utils import greet, add greet("小明")add(1,2) 只用少数几个函数,想写短一点
方式三 from my_utils import greet as say_hi say_hi("小明") 想用短名或避免和本文件同名冲突
方式四 import my_utils as utils utils.greet("小明") 模块名太长,用短别名
方式五 from my_utils import * greet("小明") 不推荐,仅小练习可偶尔用

九、同一次运行中,模块只会被加载一次

无论你用哪一种方式写了几行 import,只要模块名相同,Python 在同一次运行里只会执行该模块文件一次。之后的 import 只是复用已经加载好的那个模块,不会重复执行模块里的顶层代码。例如:

# main.py
import my_utils   # 第一次:执行 my_utils.py
import my_utils   # 第二次:不再执行,直接用已加载的

通常我们每个模块只写一行导入即可。


第四部分:常见问题与注意点

十、模块文件放在哪里?

  • 同一目录(推荐新手):把 my_utils.pymain.py 放在同一个文件夹里,在终端里进入该文件夹,执行 python main.py,即可正常 import my_utils
  • 其他目录:要把“模块所在目录”加入 sys.path,或把模块放在已在该路径下的包(package)里,才能被导入。新手先把模块和主程序放同一目录即可。

十一、模块名(文件名)的命名建议

  • 使用小写字母数字下划线,例如:my_utils.pygame_helpers.py
  • 不要用数字开头(如 1_utils.py),不要用空格连字符(如 my-utils.py),否则导入时不方便

十二、若模块里有“测试代码”,不想在导入时执行

有时模块里会写一些“只有直接运行这个文件时才执行”的测试代码,而不希望被别人 import 时执行,可以这样写:

# my_utils.py
def greet(name):
    return "你好," + name

if __name__ == "__main__":
    # 只有直接运行 python my_utils.py 时才会执行下面这段
    print(greet("测试"))

解释:直接运行 my_utils.py 时,Python 会把该文件的 __name__ 设为 "__main__",于是 if __name__ == "__main__": 成立,测试代码会执行。当别人在别的文件里写 import my_utils 时,my_utils__name__"my_utils",不是 "__main__",这段测试代码就不会执行。


十三、导入标准库或第三方库时用法一样

这五种方式不仅适用于你自己写的 .py 模块,也适用于 Python 标准库第三方库

import os
print(os.getcwd())

from math import sqrt
print(sqrt(4))   # 2.0

import math as m
print(m.pi)

from random import randint
n = randint(1, 10)

语法规则相同:模块名对应该库的包/模块名(通常和 import 时写的名字一致)。


第五部分:小结

  • 模块 = 一个 .py 文件,里面可以放函数、变量等,供其他文件导入使用。
  • 五种导入方式
    1. import 模块名 → 用 模块名.函数名
    2. from 模块名 import 函数名 → 直接用 函数名
    3. from 模块名 import 函数名 as 别名 → 用 别名
    4. import 模块名 as 别名 → 用 别名.函数名
    5. from 模块名 import * → 直接用所有公开名字(不推荐)

发表评论