欢迎来到魔幻小生的博客

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')

image

模块

模块是为了编写可维护的代码,而把函数分组放到不同文件里的行为。在 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 来完成,常用的动态导入有以下两种方式。

  1. 从模块直接导入
import importlib 
#导入a.b模块
mod = importlib.import_module( "a.b"
  1. 根据模块名,文件名导入
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 来动态加载。

posted @   魔幻小生  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示