Static method

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Thu Feb 18 12:54:44 CET 2010


mk a écrit :

> I'm trying to get print_internal_date become a static method AND to 
> refer to it in a class attribute 'tagdata' dict.
> 
> class PYFileInfo(FileInfo):
>     'python file properties'
> 
>     @staticmethod
>     def print_internal_date(filename):
>         f = open(filename + 'c', "rb")
>         data = f.read(8)
>         mtime = struct.unpack("<i", data[4:])
>         return time.asctime(time.gmtime(mtime[0]))
> 
>     tagdata = {'compiled_fname': lambda x: x + 'c',
>                 'size': os.path.getsize,
>                 'internal_date': print_internal_date
>             }
(snip)

>     def __get_props(self, value):
>         py_compile.compile(value)
>         for tag, fun in PYFileInfo.tagdata.items():
>             self[tag] = fun(value)
> 
> But:
> 
> c:/Python26/pythonw.exe -u  "C:/mp3i/finfo2.py"
> Traceback (most recent call last):
(snip)
>   File "C:/mp3i/finfo2.py", line 79, in __get_props
>     self[tag] = fun(value)
> TypeError: 'staticmethod' object is not callable
> 
> 
> I think I know where the problem is: what resides in tagdata is a static 
> method 'wrapper', not the function itself, according to:

Indeed. Sorry, I'm afraid I gave you bad advice wrt/ using a 
staticmethod here - I should know better :( (well, OTHO staticmethods 
are not something I use that often).

Anyway: here are a simplified version of your problem, a possible 
solution that _won't_ statisfy your other constraints, 2 ugly hacks that 
could work but that I don't really like, and what's possibly the "less 
worse" solution if you really need a staticmethod here.

###
class Foo1(object):
     """ simplified version of mk's code - test() fails """
     @staticmethod
     def bar(baaz):
         print baaz

     tagada = {'bar': bar}

     def test(self, baaz):
         self.tagada['bar'](baaz)


class Foo2(object):
     """ naive solution : kinda work, BUT will fail
         with the real code that has  plain functions
         in 'tagada'
     """
     @staticmethod
     def bar(baaz):
         print baaz

     tagada = {'bar': bar}

     def test(self, baaz):
         self.tagada['bar'].__get__(self)(baaz)


class Foo3(object):
     """ working solution 1 : defer the wrapping
         of 'bar' as a staticmethod
     """
     def bar(baaz):
         print baaz

     tagada = {'bar': bar}

     bar = staticmethod(bar)

     def test(self, baaz):
         self.tagada['bar'](baaz)


class Foo4(object):
     """ working solution 2 : use a lambda """
     @staticmethod
     def bar(baaz):
         print baaz

     tagada = {'bar': lambda x : Foo4.bar(x)}

     def test(self, baaz):
         self.tagada['bar'](baaz)


""" and as a "less worse" solution """

def foo5bar(baaz):
    print baaz

class Foo5(object):
     tagada = {'bar': foo5bar}

     bar = staticmethod(foo5bar)

     def test(self, baaz):
         self.tagada['bar'](baaz)


###

Another "solution" might be to write an alternate callable 
implementation of 'staticmethod' - which I'll leave as an exercise to 
the reader (...) - but that's possibly a bit overkill !-)


> http://docs.python.org/reference/datamodel.html
> 
> So, how do I get out the wrapped function out of static method without 
> class call or instance call? (to be called in self[tag] = fun(value))

cf above. None of the solutions I could came with really statisfy me, 
but well, at least 3 of them might be "good enough" depending on the 
context. As far as I'm concerned, I'd first try the last one, but YMMV

> Yes, I do know that if I just get rid of @staticmethod, this works 
> without a hitch.

But then you can't use print_internal_date as a method !-)

HTH



More information about the Python-list mailing list