python annotate function that passes parameters to another function - python

def foo(myarg, **other_args):
# do something
return bar(**other_args)
Is it possible to annotate this function in a way that would make it clear to IDEs that other_args are the arguments of function bar()? So that the IDE would provide a helpful code completion in this case.

Related

I am trying to make my own module and I want to show the users a help for the module functions

I am creating a module in which I'm defining multiple functions and I want to give the users some help regarding it, just like the help() function does. Still, I'm not quite sure how I do that, so can someone help me with it, for example, if I want help regarding this function, what will I have to do?
def shanky_calculate_average(*args):
my_average = sum(args) / len(args)
return my_average
I just want to know if I can get help in the same way as you can on things like help(pandas.read_excel)
What help() actually does is printing the function name with arguments and its docstring. Docstrings are comments directly after the function or class definition and are declared using either '''triple single quotes''' or """triple double quotes""".
So doing something like this:
def shanky_calculate_average(*args):
'''
Computes the average of the arguments.
Example: shanky_calculate_average(1,2,3,4)
'''
my_average = sum(args) / len(args)
return my_average
will result in help(shanky_calculate_average)
to print
shanky_calculate_average(*args)
Computes the average of the arguments.
Example: shanky_calculate_average(1,2,3,4)
As a sidenote, you can also access docstrings via the __doc__ property of the object like this: shanky_calculate_average.__doc__.

A partial wrapper of a python function

Given the following code,
def myfunc(a=None, b=None, c=None, **kw):
func(arga=a, argb=b, **kw)
#do something with c
def func(arga=None, argb=None, argc=None):
....
Can I replicate part of the signature of func, namely the missing args, without imitating every missing arg of func manually?
Put it more simply, I want to see argc in keywords of myfunc such that myfunc? would be different. It would contain argc. myfunc(a=None,b=None,c=None,argc=None)
#functools.wraps allows for wrapping a complete functions. Using partial can subtract args. But don't know to add.
yes, it is possible, though not trivial -
Python's introspection capabilities allow you to check all parameters the target function declares, and it is possible to build a new function programmatically that will include those attributes automatically.
I have written this for a project of mine, and had exposed the relevant code as my answer here: Signature-changing decorator: properly documenting additional argument
I will not mark this as duplicate, since the other question is more worried about documenting the new function.
If you want to give a try, with your code, maybe with something simpler, you can check the inspect.signature call from the standard library, which allows one to discover everything about parameters and default arguments of the target function.
Building a new function from this information is a bit more tricky, but possible - but one can always resort to a exec call which will can create a new function from a string template. The answer there follows this line.
I'm not sure what is being asked here either but I have here alternative code to functools.partial that might be adapted ???
(edit>)
The difference here from partial is that the mkcall argument is a string rather than a series of arguments. This string can then be formatted and analysed according to whatever appropriate requirements are needed before the target function is called.
(<edit)
def mkcall(fs, globals=None,locals=None):
class func:
def __init__(f,fcnm=None,params=None,globals=None,locals=None):
f.nm = fcnm
f.pm = params
f.globals = globals
f.locals = locals
def __call__(f):
s = f.nm + f.pm
eval(s,f.globals,f.locals)
if '(' in fs:
funcn,lbr,r = fs.partition('(')
tp = lbr + r
newf = func(funcn,tp,globals,locals)
callf = newf.__call__
else:
callf = eval(fs,globals,locals)
return callf
#call examples
# mkcall("func(arg)")
# mkcall("func")

Best practice handling parameter passed to multiple functions in classes and docstring

I have a class and multiple functions that run in succession as:
class ClassA():
def __init__(self):
....
def calc_A(self, param1, param2 ,param3):
res = self.__calc_B(param1=param1)
res_2 = self.__calc_C(res=res, param2, param3)
def __calc_B(self, param1):
return param1**2
def __calc_C(self, param1):
return res + param1
As you can see calc_A() takes in parameters for __calc_B() and __calc_C(). The original class is getting pretty complex as I need quite a number of parameters to run all the functions and I see myself repeating a lot of docstrings for params that get used in more than one function.
Question 1:
Is it best practice to just use *args for __calc_B() and __calc_C() or should it be handled in a completely different way?
Question 2:
Additionally, do I describe the parameters in the docstring in calc_A() or in every function?
*args is never best practice because looking at the function you won't know what is supposed to go into the function. Only by writing documentation to the function can a user figure out what the inputs are supposed to be. Making input parameters explicit if possible is generally favored, because they show up when the user calls help.
Docstrings mainly serve to help users who can learn what the function does by calling help(function). __calc_B and __calc_C seem to be functions that are not supposed to be used by the user, so a docstring is not strictly necessary. It is most important to choose good descriptive names for these functions so that you or someone else who needs to understand the code can figure out what it does. You could still write a docstring or comments if it's a particularly difficult function, but they don't need to be so detailed.
If you find no other alternatives, there are ways of generating docstrings dynamically but this is generally not recommended.

Python inspect: Get arguments of specific decorator

I need a script that given a function returns the arguments of a specific decorator.
Imagine the following function:
#decorator_a
#decorator_b(41,42,43)
#decorator_c(45)
def foo(self):
return 'bar'
I need a function that given foo returns the arguments of decorator_b - something like [41,42,43]. Is there a way to achieve this?
After a few hours of trying out different stuff I figured out a feasible solution:
inspect.getclosurevars(foo.__wrapped__).nonlocals
If you know the argument names of the decorator you try to inspect you can check for existence in the nonlocals dict. If it's not there, check one __wrapped__ layer higher and so on.

Python wrapper function discarding arguments

I have a setting where event handlers are always functions taking a single event argument.
But more often than not, I find myself writing handlers that doesn´t use any of the event information. So I constantly write handlers of the form:
def handler(_):
#react
In order to discard the argument.
But I wish I didn´t have to, as sometimes I want to reuse handlers as general action functions that take no arguments, and sometimes I have existing zero-arguments functions that I want to use as handlers.
My current solution is wrapping the function using a lambda:
def handler():
#react
event.addHandler(lambda _:handler())
But that seems wrong for other reasons.
My intuitive understanding of a lambda is that it is first and foremost a description of a return value, and event handlers return nothing. I feel lambdas are meant to express pure functions, and here I´m using them only to cause side effects.
Another solution would be a general decorator discarding all arguments.
def discardArgs(func):
def f(*args):
return func()
return f
But I need this in a great many places, and it seems silly having to import such a utility to every script for something so simple.
Is there a particularly standard or "pythonic" way of wrapping a function to discard all arguments?
Use *args:
def handler(*args):
#react
Then handler can take 0 arguments, or any number of position arguments.

Categories