Re: staticmethod not callable? (trying to make a Singletonmetaclass..)

Discussion in 'Python' started by Gabriel Genellina, Nov 29, 2009.

  1. En Sun, 29 Nov 2009 10:25:21 -0300, inhahe <> escribió:

    > 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,

    (I won't comment on the usefulness of such approach...)

    > 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)

    __new__ is a classmethod, not a staticmethod.

    > 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.

    Why do you insist on 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.

    Do you mean this error?
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: unbound method foo() must be called with X instan
    ce as first argument (got Y instance instead)

    This kind of check was removed in Python 3; ClassName.method_name yields a
    plain function, not an unbound method as in 2.x

    > 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\", line 68, in newnew
    > o = oldnew(obj, *args, **kwargs)
    > TypeError: 'staticmethod' object is not callable

    That's true: instances of the staticmethod type are 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..

    staticmethod is a type:

    py> staticmethod
    <type 'staticmethod'>

    Used as a decorator, it's like this:

    def b(): pass
    b = staticmethod(b)

    so b is an staticmethod instance. You can confirm this looking into the

    py> A.__dict__['b']
    <staticmethod object at 0x00BBCF70>
    py> A.b
    <function b at 0x00BE7970>

    A staticmethod instance is a descriptor; its __get__ method is invoked to
    resolve A.b (or getattr(A, "b")). If you retrieve it directly, you get the
    staticmethod object which is not callable:

    py> A.__dict__['b']()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: 'staticmethod' object is not callable

    Going back to your original goal, your code at the top is really a mess. I
    would not even use a metaclass. If you want to avoid creating more than
    one instance, just record the fact that you created it in the class
    constructor, __new__:

    class HardSingleton(object):
    "Only one instance of its subclasses may be created ever"
    _created = False
    def __new__(cls, *args, **kw):
    if cls._created:
    raise ValueError("Can't make duplicate instance of singleton
    %s" % cls.__name__)
    result = super(HardSingleton, cls).__new__(cls, *args, **kw)
    cls._created = True
    return result

    class A(HardSingleton):
    def __init__(self):
    print "A"

    s1 = A()
    s2 = A()

    Gabriel Genellina
    Gabriel Genellina, Nov 29, 2009
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michal Vitecek
    Michael Hudson
    Feb 11, 2004
  2. Nicolas Fleury

    Make staticmethod objects callable?

    Nicolas Fleury, Feb 28, 2006, in forum: Python
    Steven D'Aprano
    Mar 1, 2006
  3. Steven Bethard
    Steven Bethard
    Mar 1, 2006
  4. exiquio
    Oct 7, 2008
  5. Ulrich Eckhardt
    Peter Otten
    Jul 12, 2013

Share This Page