Python: signature with Numba - python-3.x

I have a function that is doing some computation and at a certain point is calling another one. For example, the main function is something like:
import numba
#numba.njit(some signature here)
def my_funct():
...
value = cosd(angle)
Since the function cosd is inside another function decorated with numba.njit, it has to be decorated as well, and in my case it is:
from numba import float64
#numba.njit(float64(float64))
def cosd(angle):
return np.cos(np.radians(angle))
My problem now is that in another function, the input value angle is an array and the related output is an array as well. I know that I could decorate my function as #numba.njit(float64[:](float64[:])) but doing so the function would not accept scalars anymore. How can I can tell numba that input is something like Union[float64, float64[:]]? Of course this applies to the output as well. Thanks a lot!

I finally found an answer myself.
The solution is to create a list of signatures so, for my example, it would be:
from numba import float64
#njit([float64(float64), float64[:](float64[:])])
def cosd(angle):
return np.cos(np.radians(angle))
I hope this will be helpful to others.

Related

Python decorator which adds a new parameter to a function

I have an addition function with two parameters a and b which simply adds a and b. To round this number, I have made a decorator factory which takes a decimals parameter and round the results of the addition function to the specified number of decimals. However, this requires the decimals number to be set at function definition. I am looking for a more dynamic approach.
Is it instead possible to make the decorator alter the addition function, such that the addition function gets a new parameter "decimals"? Here is my code:
import functools
def rounding(decimals):
def decorator(func):
#functools.wraps(func)
def wrapper(*args, **kwargs):
return round(func(*args, **kwargs), decimals)
return wrapper
return decorator
#rounding(decimals=2)
def addition(a: float, b: float):
return a + b
addition(a=1.0003, b=2.01)
So this makes the addition function always round to 2 decimals. What I instead want my decorator to do, is add a new arguments, such that I can call
addition(a=1.0003, b=2.01, decimals=2)
Is there a way to do this and if yes, is there a way to do this such that function docs still shows a, b and decimals instead of *args, **kwargs (for example when pressing ctrl+P in pycharm on the function)
I have just started working my way around python decorators. I have used https://realpython.com/primer-on-python-decorators/ as inspiration. I have not been able to find an existing answer on this site. The nearest I got was related to partial functions like here, but perhaps I am just searching for the wrong thing.
I am using Python 3.10.
You've made it too complicated.
You don't want a decorator which takes arguments, so you need only 2 levels of nested functions.
Simply add the decimals parameter to the function returned by the decorator.
def rounding():
#functools.wraps(func)
def wrapper(a, b, decimals):
return round(func(a, b), decimals)
return wrapper

What's the difference between the method .get() and the method .get in python? Both are appliable to dictionaries

Imagine I have a dict.
d = ['a': 1 , 'b':3]
I'm having a hard time to understand the difference between d.get and d.get().
I know that d.get() get the value from the key, like this:
print(d.get('a') )
output: 1
But when I write d.get, it shows this:
print(d.get)
output: <built-in method get of dict object at .........>
What is 'd.get' doing in my code?
I'm using python 3X
A method is literally just an attribute of an object that happens to be of type <class function>. The output you see is essentially what happens when you try to call print() on any function object, and is essentially a concise string representation that python creates for the function.
Actually calling a function is done with parentheses: d.get('a'), which means to execute the behavior the function refers to. It doesn't especially matter where the function is, though: I could do the following, and it would still work:
d = {'a': 1 , 'b':3}
freefunc = d.get
freefunc('a')
This is what the term "first class functions" refers to, when people compare python to something like Java. An entire function can be encapsulated in a variable and treated no differently than any other variable or attribute.
The short answer? There is no difference between the two methods. They are the same exact method.
The difference in your code is at when you write .get() you call the method, but when you write .get you just get a pointer (or location in the memory, to be exact) for that method, to call it later on if needed.
In the first scenario, you are calling print on the result of executing get('a'), which in this case is 1.
In your second scenario, you are calling print on the get function itself, instead of on an execution of it, which evaluates to its documentation, i.e. <built-in method get of dict object at... etc.

Passing a function (with arguments) as an argument in Python

I am measuring performance of different sorting methods using Python built-in library timeit. I would like to pass a function and an integer as arguments to the statement being tested in timeit(). I tried the following:
def sort_1(l):
...
return l_sorted
def test(f: Callable, l_len: int):
l = np.random.rand(low=-1000, high=1000, size=l_len)
f(l)
timeit.timeit(stmt=test(sort_1, l_len=10), number=1000)
... with a ValueError saying that stmt is neither a string nor callable. The error doesn't occur when I call it like this:
timeit.timeit(stmt=test, number=1000)
... but then I cannot pass any argument to test(). What is a general solution if someone wants to pass arguments to a function given as an argument? (let's say, when a method is already implemented and there is not way to pass arguments in a separate argument)
Cheers
Edit:
#jonrsharpe, thanks! The solution looks like this:
timeit.timeit(stmt='test(f=sort_1, l_len=10)', number=100, globals=globals())

tf.estimator.export.build_raw_serving_input_receiver_fn problem

I have a problem about exporting a savedmodel from an estimator of Tensorflow. My tensorflow program is using an estimator to do the CNN function, where the input is a 2D image. This is my code for the saving part.
def serving_input_rec_fn():
serving_features = {'images': tf.placeholder(shape=[None, self.num_input[0], self.num_input[1]], dtype=tf.float32)}
return tf.estimator.export.build_raw_serving_input_receiver_fn(features=serving_features)
self.model.export_savedmodel(export_dir, serving_input_rec_fn,
strip_default_attrs=True)
But when I ran export_savedmodel function, it produced the following error:
AttributeError: 'function' object has no attribute 'features'
When I checked the code, I actually provided the serving_features here. Could any one help me solve this problem?
you miss a bracket in the argument 'serving_input_rec_fn' passed to export_savedmodel, the right way should be like:
self.model.export_savedmodel(export_dir, **serving_input_rec_fn()**, strip_default_attrs=True)
Because the export_savedmodel api require a 'serving_input_receiver_fn' function, while the value of 'serving_input_rec_fn' is a function: 'serving_input_rec_fn'. You need to call 'serving_input_rec_fn()' which returns tf.estimator.export.build_raw_serving_input_receiver_fn(features=serving_features) which then returns a function: 'serving_input_receiver_fn'.
In method export_savedmodel(),
change
serving_input_rec_fn
to
serving_input_rec_fn()
In serving_input_rec_fn() change:
def serving_input_rec_fn():
...
return tf.estimator.export.build_raw_serving_input_receiver_fn(features=serving_features)
to:
def serving_input_rec_fn():
...
return tf.estimator.export.build_raw_serving_input_receiver_fn(serving_features)
As of documentation (here), build_raw_serving_input_receiver_fn function does not have a features argument
it should be like
def serving_input_rec_fn():
...
tf.estimator.export.build_raw_serving_input_receiver_fn(serving_features)()

TypeError: 'numpy.ndarray' object is not callable when import a function

Hi I am getting the following error.
TypeError: 'numpy.ndarray' object is not callable
I wrote a function module by myself,like this:
from numpy import *
import operator
def creatDataset() :
group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels = ['A','A','B','B']
return group,labels
then,I want to use this function in Microsoft's command window ,I've written some code, as follows:
import KNN
group,labels=KNN.creatDataset()
group()
when I input the code "group()",the error will appear.It's the first time that i describe the question and ask for help, maybe the description is not clear ,,please forgive me.
Since "group" is a numpy.array, you cannot call it like a function.
So "group()" will not work.
I assume, you want to see it's values, so you would have to use something like
"print(group)".

Resources