1

I am doing a hackerrack problem and I solved it but using something which I think is very unpythonic.

So, the idea is to parse a line which gives you a command and an operation on a list and to execute it on a list. I ended up with this ugly if/else logic as:

l = []
num_commands = int(raw_input())

for i in range(num_commands):
    current = raw_input().split()    
    if current[0] == 'insert':
        params = map(int, current[1:])
        l.insert(params[0], params[1])

    elif current[0] == 'print':
        print l

    elif current[0] == 'sort':
        l.sort()

    elif current[0] == 'pop':
        l.pop()

    elif current[0] == 'reverse':
        l.reverse()    

    elif current[0] == 'remove':
        l.remove(int(current[1]))

    elif current[0] == 'append':
        l.append(int(current[1]))

This is ugly but it works. I was wondering if there is a more elegant way to do the same perhaps using some dictionary lookup which binds a string to some member function for a particular object instance?

Luca
  • 10,458
  • 24
  • 107
  • 234

2 Answers2

4

Functions (and methods) can all be referenced, yes. You could create a dictionary of methods on a list object like lookup = {'remove': l.remove} which could then be used with lookup['remove'](val).

Additionally, you can retrieve attributes from an object with a string by using getattr:

getattr(alist, 'remove')(val)
g.d.d.c
  • 46,865
  • 9
  • 101
  • 111
  • Just a suggestion, if you don't have `l` when you are creating your dictionary, you can have `{'remove' : lambda l, i: l.remove(i) }` or similar to remove the dependency on the variable name – user2085282 Oct 23 '15 at 16:40
  • @user2085282 - Yes, but then you have to call it with `lookup['remove'](alist, val)`. If there will be more than one list modified this would work as well, but if it's always a single list the user is modifying the posted solution works as is. – g.d.d.c Oct 23 '15 at 16:43
  • 1
    Just a comment, it has to be getattr(alist, 'remove')(val) – Luca Oct 23 '15 at 17:04
1

So assuming that the function name that they give you is exactly the one that you call, you can do this: Calling a function of a module from a string with the function's name in Python.

result = getattr(l, current[0])() if len(current) == 1 else getattr(foo, current[0])(current[1])

Hope that helps!

Community
  • 1
  • 1
Almog
  • 731
  • 4
  • 10