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\funcs.py", 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
    class:

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

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
    Replies:
    4
    Views:
    934
    Michael Hudson
    Feb 11, 2004
  2. Nicolas Fleury

    Make staticmethod objects callable?

    Nicolas Fleury, Feb 28, 2006, in forum: Python
    Replies:
    10
    Views:
    580
    Steven D'Aprano
    Mar 1, 2006
  3. Steven Bethard
    Replies:
    0
    Views:
    272
    Steven Bethard
    Mar 1, 2006
  4. exiquio
    Replies:
    2
    Views:
    536
    exiquio
    Oct 7, 2008
  5. Ulrich Eckhardt
    Replies:
    6
    Views:
    106
    Peter Otten
    Jul 12, 2013
Loading...

Share This Page