在 Python 中使用类对函数进行分组

问题描述 投票:0回答:4

几年来我一直是一名 Python 科学程序员,随着我的程序越来越大,我发现自己遇到了一个特定的问题。我是自学成才的,所以我从未接受过任何正式培训,也没有真正花时间“正确地”使用 Python 进行编码的“约定”。

总之,就这一点而言,我发现自己总是创建一个 utils.py 文件,我将我的程序使用的所有已定义函数存储在该文件中。然后我发现自己将这些功能分组到各自的目的中。我知道的一种分组方式当然是使用类,但我不确定我的策略是否违背了实际应该使用的类。

假设我有一堆函数,它们做的事情大致相同:

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

def sub(a,b):
    return a -b

def cap(string):
    return string.title()

def lower(string):
    return string.lower()

现在显然这 4 个函数可以看作是做两个不同的目的,一个是计算,另一个是格式化。这是逻辑告诉我要做的,但我必须解决它,因为我不想初始化一个对应于 evertime 类的变量。

class calc_funcs(object):

    def __init__(self):
        pass

    @staticmethod
    def add(a,b):
        return a + b

    @staticmethod
    def sub(a, b):
        return a - b

class format_funcs(object):
    def __init__(self):
        pass

    @staticmethod
    def cap(string):
        return string.title()

    @staticmethod
    def lower(string):
        return string.lower()

现在我已经将这些方法“分组”到一个很好的包中,这使得根据它们在程序中的角色更快地找到所需的方法。

print calc_funcs.add(1,2)
print format_funcs.lower("Hello Bob")

话虽这么说,但我觉得这是一种非常“非Python”的做事方式,而且感觉很乱。我是要以正确的方式思考还是有其他方法?

python class conventions
4个回答
28
投票

另一种方法是制作一个

util
package 并将您的功能拆分到该包中的不同模块中。包的基础知识:创建一个目录(其名称将是包名称)并在其中放置一个特殊文件,即
__init__.py
文件。这个可以包含代码,但是对于基本的包组织,它可以是一个空文件。

my_package/
  __init__.py
  module1.py/
  modle2.py/
  ...
  module3.py

假设您在工作目录中:

mkdir util
touch util/__init__.py

然后在您的

util
目录中,制作
calc_funcs.py

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

def sub(a,b):
    return a -b

format_funcs.py

def cap(string):
    return string.title()

def lower(string):
    return string.lower()

现在,在您的工作目录中,您可以执行以下操作:

>>> from util import calc_funcs
>>> calc_funcs.add(1,3)
4
>>> from util.format_funcs import cap
>>> cap("the quick brown fox jumped over the lazy dog")
'The Quick Brown Fox Jumped Over The Lazy Dog'

编辑添加

注意,如果我们重新启动解释器会话:

>>> import util
>>> util.format_funcs.cap("i should've been a book")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'util' has no attribute 'format_funcs'

这就是

__init__.py
的用途!

__init__.py
中,添加以下内容:

import util.calc_funcs, util.format_funcs

现在,再次重启解释器:

>>> import util
>>> util.calc_funcs.add('1','2')
'12'
>>> util.format_funcs.lower("I DON'T KNOW WHAT I'M YELLING ABOUT")
"i don't know what i'm yelling about"

耶!通过轻松导入,我们可以灵活地控制我们的命名空间!基本上,

__init__.py
在类定义中起着类似于
__init__
方法的作用。


6
投票

我不会为此使用

class
,我会使用
module
。仅由静态方法组成的类也让我觉得代码有味道。以下是使用模块执行此操作的方法:任何时候将代码粘贴到单独的文件中并将其导入另一个文件时,Python 都会将该代码粘贴到与文件同名的模块中。所以在你的情况下:

mathutil.py

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

def sub(a,b):
    return a-b

main.py

import mathutil

def main():
    c = mathutil.add(a,b)

或者,如果你打算在很多地方使用 mathutil 并且不想每次都输入(和阅读)完整的模块名称,想出一个标准的缩写并在任何地方使用它:

main.py
,替代版本

import mathutil as mu

def main():
    c = mu.add(a,b)

与您的方法相比,您将拥有更多文件,每个文件中的功能更少,但我认为以这种方式导航代码更容易。

顺便说一下,命名文件/模块有一些 Python 约定:简称,全部小写,单词之间没有下划线。这不是我开始做的,但我已经开始在我的代码中这样做,这让我更容易理解我使用过的其他人模块的结构。


2
投票

我认为这样做完全是蟒蛇式的。这正是

staticmethod
构造函数的目的。

对于 python 约定,请参阅 PEP 8


0
投票

在我看来,这是一个非常好的方法。非常感谢你!

我猜你不需要

def __init__(self):
pass

© www.soinside.com 2019 - 2024. All rights reserved.