我问这个关于Python的问题,虽然它可能适用于大多数OOP语言。
当我只期望在任何程序中只使用一次数据模型时,我可以使用类/静态方法和属性创建一个类,或者只创建一个常规类并将其实例化一次并仅使用该一个副本。在这种情况下,哪种方法更好,为什么?
使用python,我也可以编写一个模块并像使用类一样使用它。在这种情况下,哪种方式更好,为什么?
示例:我希望有一个中央数据结构来访问/保存数据到文件。
模块方式:
data.py
attributes = something
...
def save():
...
main.py
import data
data.x = something
...
data.save()
课程方式:
class Data:
attributes = something
@classmethod
def save(cls):
Data.x = something
Data.save()
实例方式
class Data:
def save(self):
data = Data()
data.x = something
data.save()
答案 0 :(得分:5)
模块旨在将公共结构包含在“命名空间”中。但实际上在python中,模块只是一个文件,你可以根据需要组织它们。有些人在一个模块中放了很多功能。有些人将它们分散在包裹或子包装上。取决于您想要的可重用性。如果一个模块有很多依赖项,并且你只想重用一小部分,那么拆分它们是有意义的。
一个类允许您定义可以作为子类型继承的类型。它们还允许您为该类的每个实例定义一个状态。
当你的班级没有状态,只有staticmethods / classmethods时,你可能不需要一个班级。你只需要功能。
此外,您无法创建模块并像课程一样使用它。模块不能有子类。它们在加载时只有一个基本模块init,然后是一个对象范围。
如果你所追求的是常量,意味着它们在应用程序的生命周期中被定义一次,那么只需创建一个带有一堆原始类型(如字符串,字符串和列表)的constants.py模块。
答案 1 :(得分:3)
标准随机模块实现具有良好的设计,可以显示模块级实例的创建和使用,而无需强制任何用户使用单例。
例如,如果我调用random.random()
,它会使用在导入时初始化的类Random的隐藏实例。如果我对默认值不满意,我可以
my_random = random.Random()
my_random.seed('not needed but illustrative seed call')
coin_toss = my_random.random()
然后有一个不与隐藏实例共享状态的生成器。如果您对此方法感兴趣,请阅读random.py
,其中包含了很好的文档;只有少数相关的代码行并不是那么棘手。
这种方法为单身人士提供了一个有趣的Pythonic扭曲:在导入时自动构建一个,但是如果我想要的话,不要阻止我实例化。