staticmethod not callable? (trying to make a Singleton metaclass..)

inhahe inhahe at gmail.com
Sun Nov 29 08:25:21 EST 2009


I'm trying to come up with a system for singletons, where I don't have to
modify anything for an individual class except to define __metaclass__ or,
if possible, to inherit another class.

I want it to raise an error if making a duplicate instance of a class is
attempted, rather than to return the same object, because my philosophy is
that if your class is a singleton and you're trying to make another instance
of it then you're doing it wrong and you should probably know.  Although the
way I'm trying to do it could apply to either philosophy.

I've seen several solutions for singletons in Python, but I don't like them,
either because they require modification to each individual singleton class,
or they require something after the class definition like Class = Class(),
or I totally don't understand them.  The novel way I've attempted to come up
with is this:

class Singleton(type):
  def __new__(meta, classname, bases, classDict):
    @staticmethod
    def nonewinst(*args, **kwargs):
      raise ValueError("Can't make duplicate instance of singleton " +
classname)
    @staticmethod
    def newoldnew(obj):
      return obj
    oldnew = classDict.get("__new__", newoldnew)
    @staticmethod
    def newnew(obj, *args, **kwargs):
      o = oldnew(obj, *args, **kwargs)
      obj.__new__ = nonewinst
      return o
    classDict["__new__"] = newnew
    return type.__new__(meta, classname, bases, classDict)

a little bit of experimentation revealed that apparently even functions
defined within a method become class methods, so i tried making them all
static methods.  however, python is strange to me when it comes to methods
and the self parameter.  i mean i understand a function being free of the
class so that the 'self' parameter doesn't mean anything in particular
unless you explicitly pass it an instance.  and i understand the method
being bound to an object so that when it's called its self parameter is
automatically sent the instance.  but python seems to have this in-between
mode where sometimes a function isn't particularly bound to an instance but
if you try to pass the wrong kind of instance to 'self' it'll complain,
which gets annoying, and i don't understand how its binding works. but
anyway, the problem i'm currently having with the code might not even be
related to that..because here's the error I'm getting:

>>> from funcs import Singleton
>>> class A:
...   __metaclass__ = Singleton
...
>>> b = A()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python25\funcs.py", line 68, in newnew
    o = oldnew(obj, *args, **kwargs)
TypeError: 'staticmethod' object is not callable

i'm not that experienced with metaclasses, but it seems to me that
something's obviously going fubar here because at that point oldnew should
be the function newoldnew (since class A doesn't have a __new__ defined)
which is clearly defined right there with a staticmethod decorator, and
first of all, functions *should* be callable, and secondly, why is my object
a 'staticmethod' object just because I used a decorator on it?  it would
seem it should be a function, so i tested it like this:

>>> class A:
...   @staticmethod
...   def b(): pass
...
>>> type(A.b)
<type 'function'>

in that case, using @staticmethod returns a function.  i have nfi why it's
different in my Singleton class.

oh, and thirdly, staticmethod is a decorator and decorators are callables so
even given that for some mysterious reason it's a staticmethod object i
don't know why it's not callable.  so that's pretty confusing.  can anyone
clear this up for me?  thanks..

ps. i'm aware of the evils of singletons and all that.  short answer: I
don't care.  :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20091129/054b9860/attachment.html>


More information about the Python-list mailing list