1

What is the best way to use a function at the top of a module if do not know the name of the object in advance: The function might depend on user input and hence its name is stored in a variable.

One solution uses eval(): For example, in ScipyCookbook/SignalSmooth: smooth() (also referenced in an answer to StackOverflow: Python Smooth Time Series Data)

import numpy  
window = 'hanning'
w = eval('numpy.'+window+'(11)')

will be equivalent to

w = numpy.hanning(11)

However, is there a better method than using fragile/potentially dangerous eval?

For instance, wouldn't using vars()

w = vars(numpy)[window](11)

be preferred? Any better/more pythonic ideas?

Community
  • 1
  • 1
orbeckst
  • 3,189
  • 1
  • 17
  • 14

2 Answers2

4

You should use a dictionary mapping the valid window function names to the actual functions:

windows = {"bartlett": numpy.bartlett,
           "blackman": numpy.blackman,
           "hamming": numpy.hamming,
           "hanning": numpy.hanning,
           "kaiser": numpy.kaiser}

If you use eval(), the user is basically allowed to execute arbitrary code.

The variant

w = vars(numpy)[window](11)

is definitely better than using eval(), but it still does not make sure the function the user selected makes sense in the given context. (And usually, you'd use getattr() for this instead.)

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 1
    I like this a whole lot better than any other approach such as eval or getattr. This is my personal method as well. +1. What I really like about this is how manageable it is to swap out the handlers at any point. – jdi Feb 25 '12 at 17:55
  • I would argue getattr is a better option here - it requires no repeating yourself. If there is a need to change handlers, the fine, but otherwise, unnecessary. – Gareth Latty Feb 25 '12 at 19:57
  • @Lattyware: The `numpy` module contains almost 500 callable objects. Only five of them are useful as window functions. Using `getattr()` will allow all 500 functions to be used, and most of them will lead to at least strange behaviour in your program. Moreover, I don't consider this "repeating myself". I'd consider this decoupling of the user interface of our program from the API of NumPy. We map the *names* these window functions are supposed to have in the program to the *function objects* in NumPy -- there's no repetition. – Sven Marnach Feb 25 '12 at 20:09
  • @SvenMarnach Fair enough, in which case, in this situation, I'd agree that's the better option. I don't have much experience with numpy, so I was treating this as a general case. You make a good point. – Gareth Latty Feb 25 '12 at 20:23
  • I agree that a dispatch table is in general the safest approach and most appropriate for the numpy example. For other cases I'll keep `getattr()` in mind. Thanks. – orbeckst Feb 26 '12 at 02:52
4

A module's functions are attributes of the module, so you can do:

window = "hanning"
getattr(numpy, window)(11)

vars() is also fine.

kindall
  • 178,883
  • 35
  • 278
  • 309