0

I'm trying to implement the Singleton pattern in Python (2.7).

I've read severel posts (1, 2, 3, 4) about the implementation and I want to code my own version. (A version which I understand. I'm new to Python.)

So I'm creating the singleton with a method that will create my single object itself that will be returned on every Singleton.Instance() call.

But the error message is always the same:

Traceback (most recent call last):
  File "./test4.py", line 24, in <module>
    print id(s.Instance())
  File "./test4.py", line 15, in Instance
    Singleton._instance = Singleton._creator();
TypeError: unbound method foobar() must be called with Singleton instance as first argument (got nothing instead)

Here I roll:

class Singleton(object):

    _creator = None
    _instance = None

    def __init__(self, creator):
        if Singleton._creator is None and creator is not None:
            Singleton._creator = creator

    def Instance(self):

        if Singleton._instance is not None:
            return Singleton._instance

        Singleton._instance = Singleton._creator();

        return Singleton._instance;

def foobar():
    return "foobar"

s = Singleton( foobar )

print id(s.Instance())

Why is that? To be more specific: How do I call in a method a def stored in a class variable in Python?

Community
  • 1
  • 1
ewasser
  • 58
  • 4
  • I recommend to use a decorator (e.g. define your own `@singleton`) that you can apply to any class – Pynchia Jul 30 '15 at 14:13
  • Decorators are great for production code, but maybe not so much for the initial stab at code for someone who just wrote "A version which I understand. I'm new to Python." – Patrick Maupin Jul 30 '15 at 14:30

1 Answers1

0

The problem is that when you insert it into the class, Python automatically makes it a method for you. You need to make it a staticmethod to avoid this.

class Singleton(object):

    _creator = None
    _instance = None

    def __init__(self, creator):
        if Singleton._creator is None and creator is not None:
            Singleton._creator = staticmethod(creator)

    def Instance(self):

        if Singleton._instance is not None:
            return Singleton._instance

        Singleton._instance = Singleton._creator();

        return Singleton._instance;

def foobar():
    return "foobar"

s = Singleton( foobar )

print id(s.Instance())
Patrick Maupin
  • 7,331
  • 2
  • 21
  • 41
  • That's not what I meant. The singleton itself can be created multiple times. The important thing is that the `creator` will be only called once and returned multiple times. – ewasser Jul 30 '15 at 14:12
  • @ewasser -- Ah, I see, and I see the problem and have edited the answer. – Patrick Maupin Jul 30 '15 at 15:07
  • Thanks. What is `staticmethod()` for a construct? Is is also a decorator? – ewasser Jul 30 '15 at 17:59
  • Yes, it works as a decorator as well. In general, when you bind a function to the class, the interpreter assumes that it should wrap the function in an instancemethod -- that will make sure that the first thing passed is an instance of the class. But it only does this for functions that are not already instance, class, or static methods. – Patrick Maupin Jul 30 '15 at 22:29