为“只有一个实例”创建一个Python类?

时间:2012-07-26 05:46:44

标签: python oop

我问这个关于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()

2 个答案:

答案 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扭曲:在导入时自动构建一个,但是如果我想要的话,不要阻止我实例化。