3

Starting with a class like this:

class FooClass(object):
    @staticmethod
    def static_method(x):
        print x

normally, I would call the static method of the class with:

FooClass.static_method('bar')

Is it possible to invoke this static method having just the class name and the method name?

class_name = 'FooClass'
method_name = 'static_method'
3
  • 1
    Possible? Yes. A good idea? No. Only use when you absolutely must. Commented Oct 3, 2010 at 11:46
  • @delnan please, could you explain why? Commented Oct 3, 2010 at 11:58
  • 1
    For the same reason eval, exec, reflection in Java/.NET and similar features are frowned up: Potentially harder to debug, more prone to errors and security holes, slower, and atop of all this, it's rarely the easier or more elegant solution (quite the contrary, it's often harder to get this approach right than to do it properly), let alone necessary. Commented Oct 3, 2010 at 12:04

4 Answers 4

9

You shouldn't mess with locals() as suggested in other answers. If you have your classname as a string and need to resolve it, use registry of some sort. A dictionary will work fine. E.g.

class FooClass(object):
    @staticmethod
    def static_method(x):
        print x

registry = {'FooClass':FooClass}

(I assume you will want to add many more classes to this registry)

the lookup then becomes almost trivial:

getattr(registry['FooClass'], 'static_method')("bar")
Sign up to request clarification or add additional context in comments.

1 Comment

Agreed. locals and globals should be the last resort. +1.
3

Here is a crude way:

>>> class FooClass(object):
    @staticmethod
    def static_method(x):
        print x


>>> class_name = 'FooClass'
>>> method_name = 'static_method'
>>> getattr(locals().get(class_name), method_name)("bar")
bar

Breakup:

locals().get(class_name)

First, locate the class. In this case I'm using locals() as I know that the class is available in the local dictionary. This will fail if the class is not present in the local dictionary.

Next, find the method of the class.

getattr(locals().get(class_name), method_name)

This uses getattr().

Finally, call the method.

getattr(locals().get(class_name), method_name)("bar")

Comments

2

you can use getattr twice. the first time on the module that contains the class and the second time on the class itself

class_name = 'Foo'
method_name = 'Bar'

cls = getattr(mod, clsname)
method = getattr(cls, method_name)
method(args)

This is not as flexible as building a registry (which you can do with a decorator) but if you are not going to do that, than this is a far better alternative than messing with the stack and stylistically, cleaner than messing with sys.modules.

Note that a module can import itself with no adverse effects. so the classes don't have to be in a different module for this to work.

1 Comment

Your observation about how it would be better to use getattr() on the module object is well taken, because one will likely have it handy anyway. I tried to write my slightly earlier answer so it would work while making as few assumptions as possible.
1

If the class type is accessible from the current module, you can access the class in the globals() dict and the method using getattr:

class FooClass(object):
    @staticmethod
    def static_method(x):
        print x

class_name = 'FooClass'
method_name = 'static_method'

getattr(globals()[class_name], method_name)("test")

3 Comments

using globals() or locals() is an unnecessary hack
@Ivo van der Wijk: So what do you propose instead?
@Ivo van der Wijk: Didn't see your answer. The OP's use case is obviously already a hack, so why not use the standard Python dictionaries to access the class?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.