You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将同类算法函数放入空类作为容器是否为不良编程实践?

问题描述

我有几个完成相同任务但采用不同算法的函数,因为这些算法同属一个父流程,就把它们放到了my_package包下my_empty_class.py模块里的空类my_empty_class中当方法用,代码如下:

class my_empty_class:
    """Define an empty class to hold the methods"""

    def func1(param1, param2, param3):
        # algo 1
        return results

    def func2(param1, param3):
        # algo 2
        return results

    def func3(param2, param4):
        # algo 3
        return results

包的文件结构是这样的:

my_package/
    __init__.py
    my_empty_class.py
    another_module.py
    onemore_module.py
    ...

__init__.py里的内容:

from .my_empty_class import my_empty_class as my_empty_class
from .another_module import another_module as another_module
from .onemore_module import onemore_module as onemore_module
...

调用的时候是这么用的:

import my_package

res1 = my_package.my_empty_class.func1(param1, param2, param3)
res2 = my_package.my_empty_class.func2(param1, param3)
res3 = my_package.my_empty_class.func3(param2, param4)

这么做是能跑,但总感觉不太规范,有没有更推荐的实现方式?

推荐实现方式

1. 直接用模块级函数(最简洁的方案)

你现在用空类只是当个“容器”装函数,完全没必要多这一层类,直接把函数放到模块里就行——甚至可以把my_empty_class.py改个更有意义的名字,比如algorithms.py:

# my_package/algorithms.py
def func1(param1, param2, param3):
    # algo 1
    return results

def func2(param1, param3):
    # algo 2
    return results

def func3(param2, param4):
    # algo 3
    return results

然后在__init__.py里导出这些函数(或者保留模块名,看你喜欢哪种调用方式):

# 方式一:直接导出函数,调用时不用写模块名
from .algorithms import func1, func2, func3

# 方式二:保留模块名,强调分组
from .algorithms import algorithms as algorithms

调用的时候就更清爽了:

import my_package

# 方式一的调用
res1 = my_package.func1(param1, param2, param3)

# 方式二的调用
res1 = my_package.algorithms.func1(param1, param2, param3)

这完全符合Python“扁平结构优于嵌套”的设计原则,没必要为了分组硬套一个空类。

2. 用子包做命名空间(适合算法逻辑复杂的情况)

如果每个算法的代码量都很大,不想挤在一个文件里,可以专门建个algorithms子包,把每个算法拆到单独文件里:

my_package/
    __init__.py
    algorithms/
        __init__.py
        func1.py
        func2.py
        func3.py
    another_module.py
    ...

然后在algorithms/__init__.py里统一导出所有算法:

from .func1 import func1
from .func2 import func2
from .func3 import func3

调用方式和模块级函数差不多:

import my_package
res1 = my_package.algorithms.func1(...)

这种结构更清晰,后期维护单个算法也方便。

3. 抽象基类(需要规范算法接口时用)

如果你希望所有算法都遵循统一的输入输出规范,避免后续加新算法时乱写签名,可以用abc模块定义一个抽象基类,让每个算法类继承并实现接口:

from abc import ABC, abstractmethod

class BaseAlgorithm(ABC):
    @abstractmethod
    def execute(self, **kwargs):
        pass

class Algorithm1(BaseAlgorithm):
    def execute(self, param1, param2, param3):
        # algo 1
        return results

class Algorithm2(BaseAlgorithm):
    def execute(self, param1, param3):
        # algo 2
        return results

调用的时候需要先实例化类:

algo1 = Algorithm1()
res1 = algo1.execute(param1, param2, param3)

不过要是你的算法不需要保存任何状态(比如不需要实例变量),这种方式就有点多余,不如模块级函数简洁。

4. 策略模式(需要动态切换算法时用)

如果你的业务逻辑需要在运行时根据不同情况切换算法,可以用策略模式,搞个上下文类来管理算法:

class AlgorithmContext:
    def __init__(self, strategy):
        self.strategy = strategy

    def run(self, **kwargs):
        return self.strategy(**kwargs)

# 先定义好各个算法函数
def func1(param1, param2, param3):
    return results

def func2(param1, param3):
    return results

# 使用示例
context = AlgorithmContext(func1)
res1 = context.run(param1=..., param2=..., param3=...)

# 切换算法
context.strategy = func2
res2 = context.run(param1=..., param3=...)

这种方式适合需要灵活切换算法的场景,比如用户选不同的计算方式时动态调整。

内容的提问来源于stack exchange,提问作者Gabriel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 16:09:52