Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make scalar python function accept list and arrays

In python, is there an easy and efficient way to make function f(x: float) accept both lists and numpy arrays as arguments (in which case I would want to apply f element-wise and return the result in the same format as it was sent in)? For now, I need only 1-dimensional arrays.

As an illustration (my real f is more complex), let's say that I have:

def f(x):
    return math.log(x) if x > 0 else 0.0

Then this one works, but is not that elegant - and possibly not that efficient either, because of the recursion (which I use as it allows me to have just one function):

def f(x):
    if np.isscalar(x):
        return math.log(x) if x > 0 else 0.0
    elif isinstance(x, np.ndarray):
        return np.array([f(i) for i in x], dtype=float)
    else:
        return [f(i) for i in x]

Is there a better way?

like image 959
Michal Kaut Avatar asked Jan 20 '26 04:01

Michal Kaut


1 Answers

Using a decorator function would be a good option if this is something you'd need to for more than just a single function definition in your code-base. It does mean that you have to wrap your code, but I'm assuming that what you mean by "having just one function" is that you do want the function expression in f(x) to be the same for all cases.

Using your existing code, the decorator function would look like this:

def elementwise_possible(func):
    def wrapper(x):
        if np.isscalar(x):
            return func(x)
        elif isinstance(x, np.ndarray):
            return np.array([func(i) for i in x], dtype=float)
        else:
            return [func(i) for i in x]
    return wrapper 

And you would write your function like this:

@elementwise_possible
def f(x):
    return math.log(x) if x > 0 else 0.0

The resulting output becomes

In[2]: A = f(2)
In[3]: A
Out[3]: 0.6931471805599453

In[4]: B = f(np.array([2,3,4]))
In[5]: B
Out[5]: array([0.69314718, 1.09861229, 1.38629436])

In[6]:C = f([5,6,7])
In[7]:C
Out[7]: [1.6094379124341003, 1.791759469228055, 1.9459101490553132]

I think efficiency should be the same.

like image 168
ulmo Avatar answered Jan 21 '26 18:01

ulmo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!