7

I'm asking this question with regards to Python, though it's probably applicable to most OOP languages.

When I only expect to use the data model only once in any program, I could either make a class with class/static methods and attributes or just make a regular class and instantiate it once and only use that one copy. In this case, which method is better and why?

With python, I could also write a module and use it like I would a class. In this case, which way is better and why?

Example: I want to have a central data structure to access/save data to files.

Module way:

data.py

attributes = something
...
def save():
...

main.py

import data
data.x = something
...
data.save()

Class way:

class Data:
    attributes = something
    @classmethod
    def save(cls):

Data.x = something
Data.save()

instance way

class Data:
    def save(self):

data = Data()
data.x = something
data.save()
darkfeline
  • 9,404
  • 5
  • 31
  • 32
  • 4
    Why the downvote? This is a legitimate programming question. – darkfeline Jul 26 '12 at 05:59
  • 1
    search stackoverflow for `singleton python` – warvariuc Jul 26 '12 at 06:13
  • 2
    The revised question is much better. I do not think a close (except for a duplicate) is currently warranted. –  Jul 26 '12 at 06:20
  • 1
    @warwaruk: interestingly enough, using a module is the suggested way of doing singletons in python, which doesn't help answer my question at all http://stackoverflow.com/questions/31875/is-there-a-simple-elegant-way-to-define-singletons-in-python – darkfeline Jul 26 '12 at 06:24

2 Answers2

5

A module is meant to enclose common structures in a "namespace". But really in python a module is just a file and you can organize them however you want. Some people put a lot of functionality in one module. Some people spread them out over packages or sub-packages. Depends on the reusability you want. If a module has a ton of dependencies and you will want to reuse just a small amount, it makes sense to split them.

A class allows you to define types that can be inherited as sub-types. They also let you define a state with each instance of that class.

When your class has no state, and only staticmethods/classmethods, chances are you don't need a class. You just need functions.

Also, you can't create a module and use it like a class. A module can't have subclasses. They just have a basic module init once on load and then a scope of objects.

If what you are after are constants, meaning they are defined once for the life of the app, then just create a constants.py module with a bunch of primitive types like strings, dicts, and lists.

jdi
  • 90,542
  • 19
  • 167
  • 203
  • 1
    You can use a module somewhat like a class (see my example), although it seems a little hackish. I'm looking for something with state and methods, but I'll only ever need one instance, so do I use class or instance? – darkfeline Jul 26 '12 at 06:02
  • You are only using the module for its scope. Aside from being a module object, it is not like a class. Any object can have attributes. – jdi Jul 26 '12 at 06:03
  • State and methods sometimes suggest a Singleton pattern. Though some frown upon them as being bad style. If it has state and setup and needs specific functionality then it can be a normal class. You should avoid having structures that actively modify globals though. Constants are usually read only – jdi Jul 26 '12 at 06:05
  • So I would be abusing modules this way; good to know. What about class vs instance? – darkfeline Jul 26 '12 at 06:06
  • I'm not modifying globals, which is the point of OOP. I want the variables to be bound to an object, but am debating between class vs instance. Since classes are also objects in Python, what pro/cons would there be vis-a-vis using singleton and using a class (with class methods/attributes) directly? – darkfeline Jul 26 '12 at 06:11
  • From a general standpoint I can't really say there is a real pro or con. Its more about how it will be used eventually. A pro of the class I guess would be that the state is set a module load time without an instance and shared between modules importing it. – jdi Jul 26 '12 at 14:28
3

The standard random module implementation has a good design that shows both module level instance creation and use without forcing a singleton on any user.

For example if I call random.random() it uses a hidden instance of class Random which was initialized at import time. If I'm not satisfied with the default, I can

my_random = random.Random()
my_random.seed('not needed but illustrative seed call')
coin_toss = my_random.random()

and then have a generator that doesn't share state with the hidden instance. If you are interested in this approach, read random.py which is very well documented; there are only a few relevant lines of code which aren't all that tricky.

This approach gives an interesting, Pythonic twist on singletons: build one on import automatically but don't prevent me from instantiating more if I want.

msw
  • 42,753
  • 9
  • 87
  • 112