在Python中组织类和模块
我在整理模块和类的时候有点头疼。因为我之前用C++,习惯了类把所有需要处理的数据和方法都封装在一起。在Python里有模块这个概念,我看到的代码中,有些人喜欢把很多“松散”的函数放在模块里,而另一些人则几乎总是把函数作为方法绑定到类里。
举个例子,假设我有一个数据结构,想把它写入磁盘。
一种方法是为这个对象实现一个保存的方法,这样我只需要输入
MyObject.save(filename)
或者类似的东西。另一种我看到的同样常见的方法是使用
from myutils import readwrite
readwrite.save(MyObject,filename)
这是一个小例子,我不太确定这个问题在Python中特有的程度,但我想问的是,在函数和方法的组织上,什么是最好的Python风格?
2 个回答
如果你有一个普通的类想要保存到磁盘上,我建议你把它做成一个实例方法。如果是一个可以处理不同类型对象的序列化库,那我会选择第二种方法。
看起来你对松散的函数有些困扰。这其实是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文件),你就得修改每个类。如果每个类都实现一个接口来提供它想要保存的数据,那么你只需要写一个函数来保存所有类的实例,并且只需修改这个函数一次。这被称为单一职责原则:每个类应该只有一个改变的理由。