Is it possible to declare a function without arguments but then pass some arguments to that function without raising exception?
Question:
In python is it possible to have the above code without raising an exception ?
def myfunc():
pass
# TypeError myfunc() takes no arguments (1 given)
myfunc('param')
Usually in php in some circumstances I launch a function without parameters and then retrieve the parameters inside the function.
In practice I don’t want to declare arguments in myfunc and then passing some arguments to it. The only one solution I found is myfunc(*arg)
. Are there any other methods ?
Answers:
Sure can!
You can define variable length parameter lists like so:
def foo(*args):
print len(args)
args is a tuple of your parameters so calling:
foo(1,2)
gives you the tuple (1, 2) inside your function.
There are two ways to pass args in
By Position
>>> def myfunc(*args):
... print "args", args
...
>>> myfunc("param")
args ('param',)
By Keyword
>>> def myfunc(**kw):
... print "kw", kw
...
>>> myfunc(param="param")
kw {'param': 'param'}
And you can use a combination of both
>>> def myfunc(*args, **kw):
... print "args", args
... print "kw", kw
...
>>> myfunc("param")
args ('param',)
kw {}
>>>
>>> myfunc(param="param")
args ()
kw {'param': 'param'}
>>>
>>> myfunc("param", anotherparam="anotherparam")
args ('param',)
kw {'anotherparam': 'anotherparam'}
>>> def myFunc(*args, **kwargs):
... # This function accepts arbitary arguments:
... # Keywords arguments are available in the kwargs dict;
... # Regular arguments are in the args tuple.
... # (This behaviour is dictated by the stars, not by
... # the name of the formal parameters.)
... print args, kwargs
...
>>> myFunc()
() {}
>>> myFunc(2)
(2,) {}
>>> myFunc(2,5)
(2, 5) {}
>>> myFunc(b = 3)
() {'b': 3}
>>> import dis
>>> dis.dis(myFunc)
1 0 LOAD_FAST 0 (args)
3 PRINT_ITEM
4 LOAD_FAST 1 (kwargs)
7 PRINT_ITEM
8 PRINT_NEWLINE
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
And to actually answer the question: no, I do not believe there are other ways.
The main reason is pretty simple: C python is stack based. A function that doesn’t require parameters will not have space allocated for it on the stack (myFunc
, instead, has them in position 0 and 1). (see comments)
An additional point is, how would you access the parameters otherwise?
Here is a function decorator I wrote to do just that, along with an example of usage:
def IgnoreExtraArguments(f):
import types
c = f.func_code
if c.co_flags & 0x04 or c.co_flags&0x08:
raise ValueError('function already accepts optional arguments')
newc = types.CodeType(c.co_argcount,
c.co_nlocals,
c.co_stacksize,
c.co_flags | 0x04 | 0x08,
c.co_code,
c.co_consts,
c.co_names,
c.co_varnames+('_ignore_args','_ignore_kwargs'),
c.co_filename,
c.co_name,
c.co_firstlineno,
c.co_lnotab,
c.co_freevars,
c.co_cellvars)
f.func_code = newc
return f
if __name__ == "__main__":
def f(x,y):
print x+y
g = IgnoreExtraArguments(f)
g(2,4)
g(2,5,'banana')
class C(object):
@IgnoreExtraArguments
def m(self,x,y):
print x-y
a=C()
a.m(3,5)
a.m(3,6,'apple')
> def vf(a=0):
> aw = a + 5
> print(aw)
>
> vf() result: 5
> vf(5) result: 10
In python is it possible to have the above code without raising an exception ?
def myfunc():
pass
# TypeError myfunc() takes no arguments (1 given)
myfunc('param')
Usually in php in some circumstances I launch a function without parameters and then retrieve the parameters inside the function.
In practice I don’t want to declare arguments in myfunc and then passing some arguments to it. The only one solution I found is myfunc(*arg)
. Are there any other methods ?
Sure can!
You can define variable length parameter lists like so:
def foo(*args):
print len(args)
args is a tuple of your parameters so calling:
foo(1,2)
gives you the tuple (1, 2) inside your function.
There are two ways to pass args in
By Position
>>> def myfunc(*args):
... print "args", args
...
>>> myfunc("param")
args ('param',)
By Keyword
>>> def myfunc(**kw):
... print "kw", kw
...
>>> myfunc(param="param")
kw {'param': 'param'}
And you can use a combination of both
>>> def myfunc(*args, **kw):
... print "args", args
... print "kw", kw
...
>>> myfunc("param")
args ('param',)
kw {}
>>>
>>> myfunc(param="param")
args ()
kw {'param': 'param'}
>>>
>>> myfunc("param", anotherparam="anotherparam")
args ('param',)
kw {'anotherparam': 'anotherparam'}
>>> def myFunc(*args, **kwargs):
... # This function accepts arbitary arguments:
... # Keywords arguments are available in the kwargs dict;
... # Regular arguments are in the args tuple.
... # (This behaviour is dictated by the stars, not by
... # the name of the formal parameters.)
... print args, kwargs
...
>>> myFunc()
() {}
>>> myFunc(2)
(2,) {}
>>> myFunc(2,5)
(2, 5) {}
>>> myFunc(b = 3)
() {'b': 3}
>>> import dis
>>> dis.dis(myFunc)
1 0 LOAD_FAST 0 (args)
3 PRINT_ITEM
4 LOAD_FAST 1 (kwargs)
7 PRINT_ITEM
8 PRINT_NEWLINE
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
And to actually answer the question: no, I do not believe there are other ways.
The main reason is pretty simple: C python is stack based. A function that doesn’t require parameters will not have space allocated for it on the stack ( (see comments)myFunc
, instead, has them in position 0 and 1).
An additional point is, how would you access the parameters otherwise?
Here is a function decorator I wrote to do just that, along with an example of usage:
def IgnoreExtraArguments(f):
import types
c = f.func_code
if c.co_flags & 0x04 or c.co_flags&0x08:
raise ValueError('function already accepts optional arguments')
newc = types.CodeType(c.co_argcount,
c.co_nlocals,
c.co_stacksize,
c.co_flags | 0x04 | 0x08,
c.co_code,
c.co_consts,
c.co_names,
c.co_varnames+('_ignore_args','_ignore_kwargs'),
c.co_filename,
c.co_name,
c.co_firstlineno,
c.co_lnotab,
c.co_freevars,
c.co_cellvars)
f.func_code = newc
return f
if __name__ == "__main__":
def f(x,y):
print x+y
g = IgnoreExtraArguments(f)
g(2,4)
g(2,5,'banana')
class C(object):
@IgnoreExtraArguments
def m(self,x,y):
print x-y
a=C()
a.m(3,5)
a.m(3,6,'apple')
> def vf(a=0):
> aw = a + 5
> print(aw)
>
> vf() result: 5
> vf(5) result: 10