3

I am having problems passing a method in a function. I have already looked at this previous post.

How do I pass a method as a parameter in Python

Here is a simple example of what I tried.

def passMethod(obj, method):
    return obj.method()

passMethod('Hi', lower)

In the end I will use this to help write a function dealing with GIS (Geographic Information Systems) data. The data is like an array. I want to add a new column NAME1 to the array. The array then has a method to call the column array.NAME1.

Regards, Alex

Community
  • 1
  • 1
Alex
  • 313
  • 3
  • 11
  • Are you familiar with `map`? And maybe a little `__iter__`? – cheeken May 14 '12 at 21:42
  • I'm not sure why you would want to pass a method around in this manner (though there are legitimate use-cases, some context for why you want this would be nice). If you're unfamiliar with python, you might not realize you can just pass around `'Hi'.lower`. This will give you a callable object that returns `'hi'`. – Casey Kuball May 14 '12 at 21:52
  • @Darthfett I tried to provide some context in the last paragraph; but in the abstract it is hard to understand. Basically, I have an object that has methods relating to variable names in a dataset. I want to write a function that allows users to choose the variable, and hence the method that is needed. Thus I cannot hardcode the method into my function; e.g., using 'Hi'.lower is insufficient because sometimes the variable might be called upper, or even foo. – Alex May 14 '12 at 22:00
  • @AlexOlssen I'm still a little unsure of exactly what you need. The [attrgetter](http://docs.python.org/library/operator.html#operator.attrgetter) function provided by the operator module *may* be useful for your scenario, if using `getattr` can't do everything you need. – Casey Kuball May 14 '12 at 22:07

3 Answers3

5

When you give the name lower, that means to look up the name lower in the global namespace. It isn't there, because you're looking for the lower method of strings (the str class). That is spelled str.lower.

Then, in your function, obj.method means to look up the method attribute of the obj. It has nothing to do with the parameter named method, and cannot work that way. Instead, since you have an unbound method, pass the object as the self parameter explicitly: thus, method(obj). That gives us:

def passMethod(obj, method):
    return method(obj)

passMethod('Hi', str.lower)

Alternately, we could use a string as the name of the method to look up on the passed-in object. That looks like:

def passMethod(obj, method):
    return getattr(obj, method)()

passMethod('Hi', 'lower')
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • The first two lines of code in [this article](http://effbot.org/zone/python-getattr.htm) are equivalent: `value = obj.attribute` `value = getattr(obj, "attribute")`. I think that should give you an idea of what the second example looks like without the `passMethod` function. – Casey Kuball May 14 '12 at 21:44
1

I'm not exactly sure what you want, but it makes more sense to pass the method name as a string:

def passMethod(obj, method_name):
    return getattr(obj, method_name)()

passMethod('Hi', 'lower')
Ali Afshar
  • 40,967
  • 12
  • 95
  • 109
0

Well, the first problem is that you're invoking the method before you return it. Instead of returning obj.method() just return obj.method.

class Foo:
    def bar(self):
        print 'foobar!'

def pass_bar(obj):
    return obj.bar

f = Foo()
method = pass_bar(f)
method() # prints 'foobar!'

The other question is what exactly you're passing in to tell the code which method you want. A string maybe? If so, try something like

def pass_method(obj, method_name):
    return getattr(method_name)
Julian
  • 2,483
  • 20
  • 20