views:

91

answers:

2

In PHP, I can do something like this:

class MyClass
{
  function __call($name, $args)
  {
    print('you tried to call a the method named: ' . $name);
  }
}
$Obj = new MyClass();
$Obj->nonexistant_method();   // prints "you tried to call a method named: nonexistant_method"

This would be handy to be able to do in Python for a project I'm working on (lots of nasty XML to parse, it'd be nice to turn it into objects and be able to just call methods.

Does Python have an equivalent?

+1  A: 

You probably want __getattr__, although it works on class attributes as well as methods (because methods are just attributes that are functions).

Daniel Roseman
+3  A: 

Define a __getattr__ method on your object, and return a function (or a closure) from it.

In [1]: class A:
   ...:     def __getattr__(self, name):
   ...:         def function():
   ...:             print("You tried to call a method named: %s" % name)
   ...:         return function
   ...:     
   ...:     

In [2]: a = A()

In [3]: a.test()
You tried to call a method named: test
Juliano
Pretty good, although it might also be useful to define the nested function as `function(*args)` so that the body can use both the function name and any arguments passed. Depends on what Keith wants the methods to do. (Of course if there won't ever be any arguments to any of the methods, `__getattr__` itself could return the result, thereby simulating fields instead of methods.)
Richard Fearn
I do in fact want to be able to get the function arguments as well. Is the only neccessary change to define def function(): as def function(*args):? Or do I need to do something else too? (Python newbie, sorry!)
Keith Palmer
@Keith: If the function takes arbitrary arguments, then put `*args` in the argument list and it will receive a tuple with all the arguments. If it is a fixed number of arguments, then you can just go ahead and define `function(a, b)` directly, for example, to take two arguments.
Juliano
@Juliano: Thanks!
Keith Palmer