import inspect
def foo(a, b, x='blah'):
pass
print(inspect.signature(foo))
# (a, b, x='blah')
Python 3.5+ recommends inspect.signature().
python - How can I read a function's signature including default argument values? - Stack Overflow
python - What is a function signature? - Stack Overflow
Helping people understand function signature syntax - Documentation - Discussions on Python.org
code golf - Valid python function invocation signatures - Code Golf Stack Exchange
Videos
import inspect
def foo(a, b, x='blah'):
pass
print(inspect.signature(foo))
# (a, b, x='blah')
Python 3.5+ recommends inspect.signature().
Arguably the easiest way to find the signature for a function would be help(function):
>>> def function(arg1, arg2="foo", *args, **kwargs): pass
>>> help(function)
Help on function function in module __main__:
function(arg1, arg2='foo', *args, **kwargs)
Also, in Python 3 a method was added to the inspect module called signature, which is designed to represent the signature of a callable object and its return annotation:
>>> from inspect import signature
>>> def foo(a, *, b:int, **kwargs):
... pass
>>> sig = signature(foo)
>>> str(sig)
'(a, *, b:int, **kwargs)'
>>> str(sig.parameters['b'])
'b:int'
>>> sig.parameters['b'].annotation
<class 'int'>
In general the signature of a function is defined by the number and type of input arguments the function takes and the type of the result the function returns.
As an example in C++ consider the following function:
int multiply(int x, int y){
return x*y;
}
The signature of that function, described in an abstract way would be the set {int, int, int}.
As Python is a weakly typed language in general the signature is only given by the amount of parameters. But in newer Python versions type hints were introduced which clarify the signature:
def multiply(x: int, y: int) -> int:
return x*y
The signature indicates the names and types of the input arguments, and (with type annotations) the type of the returned result(s) of a function or method.
This is not particular to Python, though the concept is more central in some other languages (like C++, where the same method name can exist with multiple signatures, and the types of the input arguments determine which one will be called).
Python3, 302 bytes
from itertools import*
V=lambda v:not any(not v[i][0] and v[i-1][0]for i in range(len(v))if i)
def f(a,b,c):
P=product(*[*[[(None,t)]+[[]]*k for n,t,k in a],*[[(None,t),(n,t)]+[[]]*k for n,t,k in b],*[[(n,t)]+[[]]*k for n,t,k in c]])
return[*map(eval,{str(K)for i in P if V(K:=[j for j in i if j])})]
Try it online!
For those interested, here is a larger solution which parses the function signature:
import ast
from itertools import*
A=lambda x:x.annotation.id
H=lambda v:not any(not v[i][0] and v[i-1][0]for i in range(len(v))if i)
def f(s):
a=ast.parse(s).body[0].args
V=['kw_defaults','defaults']
d=sum(len(getattr(a,i))for i in V)
l=sum(len(i)for j in a._fields if(i:=getattr(a,j))and j not in V)
K=0
P=product(*[*[[(None,A(i))]for i in a.posonlyargs if(K:=K+1)],*[[(None,A(i)),(i.arg,A(i))]+[[]]*(((K:=K+1))>l-d)for i in a.args],*[[(i.arg,A(i)),[]]for i in a.kwonlyargs]])
return[K for i in P if H(K:=[j for j in i if j])]
Try it online!
Haskell, 208 bytes
import Data.List
y=elem '='
o(a:b)=[c++d|d<-o b,c<-[a]:[[]|y a]];o[]=[[]]
s s=inits s`zip`tails s
i(p,a,n)=nub[(map(\\"=")d,map((++"=").(\\"="))g)|(b,c)<-s$a,(d,e)<-s$p++b,all y e,f<-o$c++n,g<-permutations f]
Try it online!
The idea here is to split the semipositionals into positional or named. The default-having positionals can be omitted when trailing all mere positionals. The named can be omitted when default-having. The named can be freely permuted, while the positionals cannot.
Hi everyone,
I've been exploring the use of / and * in Python function signatures to specify positional-only and keyword-only arguments. I understand the syntax, but I'm curious about their practical implications and best practices. I am coding for more than two years now and have never used them myself and i see them really rarely. That's why would like to learn about others experiance and maybe get some advice when it is appropriate to use them in my own functions?
Looking forward to your insights! Thanks!