python 函数、模块、包
函数、模块、包
函数
函数就是能实现一定功能的代码语句的集合。
def 函数名(参数):
函数体
跟其他语言一样, Python 函数定义同样支持无形参、有形参、可变参数等;而函数可以有返回值,也可以没有返回值。
- 无形参—不需要参数输入
# 无形参,无返回值
def print_log():
print(''' Welcome to Kevin's class ! ''')
if __name__ == "__main__":
print_log()
- 有形参—函数接受用户参数
#有一个形参,有返回值
def is_true(x):
return x > 0
# 有两个形参,有返回值
def min_number(x, y):
if x>=y:
x,y = y, x
return x
#有可变个形参, 有返回值
def sum_number(*args):
total = 0
for k in args:
total +=k
return total
#可变个形参,接受key-value的形式, 无返回值
def count_student(**kwargs):
for k, v in kwargs.items():
print('{0} - {1}'.format(k, v))
if __name__ == "__main__":
print(is_true(-2))
total = sum_number(1, 2)
print(total)
min = min_number(1, 2)
print(min)
count_student(math='kevin', logic='emily')
模块
模块是为了编写可维护的代码,而把函数分组放到不同文件里的行为。在 Python 中,一个 .py文件 就是一个模块,一个模块可以包括一个或多个功能,模块又可以被一个或多个其他模块引用。
- 提高编程效率,增强代码可维护性
把模块导入当前模块,当前模块即可拥有模块已经实现的功能。如果模块的功能本身需要更改,我们只需要更改模块定义的地方即可,其他地方都无须更改。
- 不同模块的函数名和变量名可以重名
有了模块,避免了函数名和变量名之间的冲突,例如如下的文件结构:
myproject
|--module1.py
|--module2.py
假设我在 module1.py 里和 module2.py 里,同时定义一个名字为 take_picture() 的函数。这两个不同模块的函数虽然都叫 take_picutre,但其行为可以不相同,也不会相互影响。
包
包(Package)可以用于解决模块名称相同的问题。包就是一个目录文件,它必须包含一个名为 __init__.py
的文件。
myproject
|-- web
|-- module.py
|-- __init__.py
|-- API
|-- module.py
|-- __init__.py
|-- __init__.py
在 web 层级和 API 层级它们都包含着名字相同的模块 module.py,以下列出不同包下的模块引用方式:
# 引入web目录下的包, 假设此目录下module.py里有类变量Module
from web.module import Module
# 引入API目录下的包,假设此目录下module.py里有类变量Module
from API.module import Module
模块的导入
- 直接导入
import module1
module1.take_picture()
- from...import 方式导入
有时候我们并不想把一个模块的所有功能都导入进来,假设我只想使用 take_picture 这一个方法,那么我可以使用 from...import 的方式:
from module1 import take_picture
take_picture()
- from...import* 方式导入
如果你想一次性地导入一个模块下的所有函数, 你可以使用如下方式:
from module1 import *
- 动态导入
但在实际应用中,也会有在程序运行时才知道要具体导入哪个模块的情况(例如,测试框架自动查找测试用例并导入测试用例所属的模块),这时就需要动态导入。
动态导入常常用 importlib 来完成,常用的动态导入有以下两种方式。
- 从模块直接导入
import importlib
#导入a.b模块
mod = importlib.import_module( "a.b")
- 根据模块名,文件名导入
import importlib.util
spec = importlib.util.spec_from_file_location("a.b", "/path/to/file.py")
md = importlib.util.module_from_spec(spec)
spec.loader.exec_module(md)
下面我来举个具体的例子, 假设现在我们的项目目录情况如下:
myproject
|-- tests
|-- a.py
|-- __init__.py
|-- b.py
在模块 a.py 里,我定义了一个函数:
def hello():
print('i am module a!')
然后在模块 b.py 中使用hello()函数
#b.py
import os
import glob
import importlib.util
def find_modules_from_folder(folder):
absolute_f = os.path.abspath(folder)
md = glob.glob(os.path.join(absolute_f, "**/*.py"))
return [(os.path.basename(f)[:-3], f) for f in md if os.path.isfile(f) and not f.endswith('__init__.py')]
def import_modules_dynamically(mod, file_path):
spec = importlib.util.spec_from_file_location(mod, file_path)
md = importlib.util.module_from_spec(spec)
spec.loader.exec_module(md)
return md
if __name__ == "__main__":
module = find_modules_from_folder('.')
for m in module:
mod = import_modules_dynamically(m[0], m[1])
mod.hello()
这个代码有点复杂,我先给定一个文件夹,然后通过函数 find_modules_from_folder 来得到这个文件夹下的模块,及其对应的文件路径,然后我再通过 spec_from_file_location 来动态加载。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析