在Python中组织类和模块

13 投票
2 回答
5038 浏览
提问于 2025-04-16 02:53

我在整理模块和类的时候有点头疼。因为我之前用C++,习惯了类把所有需要处理的数据和方法都封装在一起。在Python里有模块这个概念,我看到的代码中,有些人喜欢把很多“松散”的函数放在模块里,而另一些人则几乎总是把函数作为方法绑定到类里。

举个例子,假设我有一个数据结构,想把它写入磁盘。

一种方法是为这个对象实现一个保存的方法,这样我只需要输入

MyObject.save(filename)

或者类似的东西。另一种我看到的同样常见的方法是使用

from myutils import readwrite

readwrite.save(MyObject,filename)

这是一个小例子,我不太确定这个问题在Python中特有的程度,但我想问的是,在函数和方法的组织上,什么是最好的Python风格?

2 个回答

3

如果你有一个普通的类想要保存到磁盘上,我建议你把它做成一个实例方法。如果是一个可以处理不同类型对象的序列化库,那我会选择第二种方法。

16

看起来你对松散的函数有些困扰。这其实是Python的写法。这样做是有道理的,因为在Python中,一个模块实际上就是一个对象,和其他对象没有什么区别。虽然语言本身支持从文件中加载模块,但除此之外,它就是一个普通的对象。

比如我有一个模块叫做 foo.py

import pprint

def show(obj):
    pprint(obj)

当我从 bar.py 中导入它时:

import foo

class fubar(object):
   #code

   def method(self, obj):
       #more stuff
       foo.show(obj)

我实际上是在访问 foo 对象上的一个方法。foo 模块的数据属性就是在 foo 中定义的全局变量。模块是语言层面实现的单例,不需要在每个方法的参数列表前加上 self

我尽量写尽可能多的模块级函数。如果某个函数只能在特定类的实例上工作,我就把它做成这个类的方法。否则,我会尽量让它能在模块中定义的每个类的实例上都能工作,只要这样做是合理的。

你提到的具体例子的背后逻辑是,如果每个类都有一个保存方法,那么如果你以后改变了保存数据的方式(比如从文件系统改成数据库或远程XML文件),你就得修改每个类。如果每个类都实现一个接口来提供它想要保存的数据,那么你只需要写一个函数来保存所有类的实例,并且只需修改这个函数一次。这被称为单一职责原则:每个类应该只有一个改变的理由。

撰写回答