0

Suppose I've got a set of background data measurements for different frequencies:

import numpy as np

C_bg_100kHz = 100*np.random.random(1000)
C_bg_200kHz = 200*np.random.random(1000)

Where C_bg_100kHz is some background noise for 100kHz measurements, and C_bg_200kHz is background noise for 200kHz measurements. I would like to create a function that subtracts the mean of these background data measurements from some array of measurement data, where I can specify as one of the function parameters which background data set I want to subtract. I have managed to make this fuction using eval():

def subtract(array_y,freq):
    bg = eval('C_bg_' + freq)
    return array_y - np.ones(len(array_y))*np.mean(bg)
>>> subtract([50,50,50],'100kHz')
array([-0.36224706, -0.36224706, -0.36224706])

>>> subtract([50,50,50],'200kHz')
array([-47.95860607, -47.95860607, -47.95860607])

Here, I can enter my data as array_y and subtract, for instance, the C_bg_100kHz dataset by passing '100kHz' as the freq input. Essentially, I want python to translate a string 'C_bg_100kHz' to the array C_bg_100kHz. However, this function uses eval(), which I've seen mentioned as something you don't want to do if you can avoid it. So, my question is whether I can avoid using eval() for this specific situation.

3
  • 5
    Yes, use a dictionary that maps string-names to the corresponding data. E.g. data = {'C_bg_100kHz': ..., 'C_bg_200kHz': ...}. Or just store the frequency as a numeric type and pass freq as a number, then access data = {100: ..., 200: ...}. Commented Jun 14, 2022 at 10:25
  • don't use separated variables but keep as dictionary - C_bg["100kHz"] = 100*np.random.random(1000) Commented Jun 14, 2022 at 10:26
  • 1
    There are a few other questions like this but the above is the first one I found. Commented Jun 14, 2022 at 10:27

1 Answer 1

0

I've found the below approach pretty flexible for me...

Put all those methods you want to dynamically call in a class, then call inspect to get the methods within that class - that'll return a list of tuple pairs that are callable, then push them into a dictionary...

import inspect

class testClass:

    def __init__(self):
        # Unfortunately, need to do this to make inspect work
        pass

    def foo1(self):
        print("Inside foo1")

    def foo2(self):
        print("Inside foo2")

myMethods = {row[0]:row[1] for row in inspect.getmembers(testClass(), predicate=inspect.ismethod)}
#Note, I am instantiating testClass for the above to work

# myMethods is now a dict of methods, so if you had a string coming out of your earlier work that was "foo1", 

str1 = "foo1"
myMethods[str1]()

>>> "Inside foo1"

Of course, you can pass parameters in, I'd suggest wrapping them up as kwargs for flexibility.

It is of course, just a fork off what has been suggested above by timgeb - but I don't like the idea of two points of truth within code. Here, when you update the class "testClass" or whatever you call it with a new method - or renamed method, then that automatically passes through to your calling algorithm, rather than having to manually update a dict.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.