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

时间:2021-09-14 22:42:11

I have been a Python Scientific Programmer for a few years now, and I find myself coming to a sort specific problem as my programs get larger and larger. I am self taught so I have never had any formal training and spent any time really on 'conventions' of coding in Python "properly".

我已经成为Python科学程序员已有几年了,随着程序越来越大,我发现自己遇到了一个特定的问题。我是自学成才,因此我从未接受过任何正式的培训,并且花了很多时间在“正确”的Python编码“惯例”上。

Anyways, to the point, I find myself always creating a utils.py file that I store all my defined functions in that my programs use. I then find myself grouping these functions into their respective purposes. One way of I know of grouping things is of course using Classes, but I am unsure as to whether my strategy goes against what classes should actually be used for.

无论如何,到目前为止,我发现自己总是创建一个utils.py文件,我将所有已定义的函数存储在我的程序使用的文件中。然后我发现自己将这些功能分组到各自的目的中。我知道对事物进行分组的一种方法当然是使用类,但我不确定我的策略是否违背实际应该使用的类。

Say I have a bunch of functions that do roughly the same thing like this:

假设我有一堆功能大致相同的事情:

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

Now obviously these 4 functions can be seen as doing two seperate purposes one is calculation and the other is formatting. This is what logic tells me to do, but I have to work around it since I don't want to initialise a variable that corresponds to the class evertime.

现在显然这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()

This way I have now 'grouped' these methods together into a nice package that makes finding desired methods much faster based on their role in the program.

通过这种方式,我现在将这些方法“分组”到一个很好的包中,根据它们在程序中的角色,可以更快地找到所需的方法。

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

However that being said, I feel this is a very 'unpython-y' way to do things, and it just feels messy. Am I going about thinking this the right way or is there an alternate method?

然而,话虽如此,我觉得这是一种非常'unpython-y'的做事方式,它只是感觉很乱。我是想以正确的方式思考这个还是有另一种方法?

3 个解决方案

#1


10  

Another approach is to make a util package and split up your functions into different modules within that package. The basics of packages: make a directory (whose name will be the package name) and put a special file in it, the __init__.py file. This can contain code, but for the basic package organization, it can be an empty file.

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

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

So say you are in your working directory:

所以说你在你的工作目录中:

mkdir util
touch util/__init__.py

Then inside your util directory, make calc_funcs.py

然后在您的util目录中,生成calc_funcs.py

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

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

And format_funcs.py:

并且format_funcs.py:

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

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

And now, from your working directory, you can do things like the following:

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

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

Edited to add

Notice, though, if we restart the interpreter session:

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

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

This is what the __init__.py is for!

这就是__init__.py的用途!

In __init__.py, add the following:

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

import util.calc_funcs, util.format_funcs

Now, restart the interpreter again:

现在,再次重启解释器:

>>> 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"

Yay! We have flexible control over our namespaces with easy importing! Basically, the __init__.py plays an analogous role to the __init__ method in a class definition.

好极了!我们可以通过轻松导入灵活控制命名空间!基本上,__ init__.py在类定义中与__init__方法起类似的作用。

#2


0  

I think doing so is perfectly pythonic. This is exactly the purpose of staticmethod constructor.

我认为这样做完全是pythonic。这正是staticmethod构造函数的目的。

For python conventions, see PEP 8.

有关python约定,请参阅PEP 8。

#3


0  

I wouldn't use a class for this, I'd use a module. A class consisting of only staticmethods strikes me as a code smell too. Here's how to do it with modules: any time you stick code in a separate file and import it into another file, Python sticks that code in a module with the same name as the file. So in your case:

我不会为此使用类,我会使用一个模块。一个只包含静态方法的类也会让我感觉像代码一样。以下是如何使用模块执行此操作:只要将代码粘贴到单独的文件中并将其导入另一个文件,Python就会将该代码粘贴到与文件同名的模块中。所以在你的情况下:

In mathutil.py

在mathutil.py中

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

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

In main.py

在main.py中

import mathutil

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

Or, if you're going to use mathutil in a lot of places and don't want to type out (and read) the full module name each time, come up with a standard abbreviation and use that everywhere:

或者,如果您要在很多地方使用mathutil并且不想每次输出(并读取)完整的模块名称,请提出标准缩写并在任何地方使用:

In main.py, alternate version

在main.py中,备用版本

import mathutil as mu

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

Compared to your method you'll have more files with fewer functions in each of them, but I think it's easier to navigate your code that way.

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

By the way, there is a bit of a Python convention for naming files/modules: short names, all lower case, without underscores between words. It's not what I started out doing, but I've moved over to doing it that way in my code and it's made it easier to understand the structure of other people's modules that I've used.

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

#1


10  

Another approach is to make a util package and split up your functions into different modules within that package. The basics of packages: make a directory (whose name will be the package name) and put a special file in it, the __init__.py file. This can contain code, but for the basic package organization, it can be an empty file.

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

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

So say you are in your working directory:

所以说你在你的工作目录中:

mkdir util
touch util/__init__.py

Then inside your util directory, make calc_funcs.py

然后在您的util目录中,生成calc_funcs.py

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

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

And format_funcs.py:

并且format_funcs.py:

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

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

And now, from your working directory, you can do things like the following:

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

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

Edited to add

Notice, though, if we restart the interpreter session:

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

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

This is what the __init__.py is for!

这就是__init__.py的用途!

In __init__.py, add the following:

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

import util.calc_funcs, util.format_funcs

Now, restart the interpreter again:

现在,再次重启解释器:

>>> 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"

Yay! We have flexible control over our namespaces with easy importing! Basically, the __init__.py plays an analogous role to the __init__ method in a class definition.

好极了!我们可以通过轻松导入灵活控制命名空间!基本上,__ init__.py在类定义中与__init__方法起类似的作用。

#2


0  

I think doing so is perfectly pythonic. This is exactly the purpose of staticmethod constructor.

我认为这样做完全是pythonic。这正是staticmethod构造函数的目的。

For python conventions, see PEP 8.

有关python约定,请参阅PEP 8。

#3


0  

I wouldn't use a class for this, I'd use a module. A class consisting of only staticmethods strikes me as a code smell too. Here's how to do it with modules: any time you stick code in a separate file and import it into another file, Python sticks that code in a module with the same name as the file. So in your case:

我不会为此使用类,我会使用一个模块。一个只包含静态方法的类也会让我感觉像代码一样。以下是如何使用模块执行此操作:只要将代码粘贴到单独的文件中并将其导入另一个文件,Python就会将该代码粘贴到与文件同名的模块中。所以在你的情况下:

In mathutil.py

在mathutil.py中

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

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

In main.py

在main.py中

import mathutil

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

Or, if you're going to use mathutil in a lot of places and don't want to type out (and read) the full module name each time, come up with a standard abbreviation and use that everywhere:

或者,如果您要在很多地方使用mathutil并且不想每次输出(并读取)完整的模块名称,请提出标准缩写并在任何地方使用:

In main.py, alternate version

在main.py中,备用版本

import mathutil as mu

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

Compared to your method you'll have more files with fewer functions in each of them, but I think it's easier to navigate your code that way.

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

By the way, there is a bit of a Python convention for naming files/modules: short names, all lower case, without underscores between words. It's not what I started out doing, but I've moved over to doing it that way in my code and it's made it easier to understand the structure of other people's modules that I've used.

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

相关文章