Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
zero or one argument
#1
is there a way for a function to accept zero or one argument without using variable arguments?
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
Not that i am aware of
>>> def func(*arg):
...     print(arg)
... 
>>> func()
()
>>> func('test')
('test',)
>>> func('test', 2)
('test', 2)
but i guess if you want to restrict more than 2 arguments you can just assert the length of arg to 2 or less
Recommended Tutorials:
Reply
#3
ok, then i'm stuck with variable arguments.  i was wanting to do something like:
def myfun(myarg=None):
    if myarg is None:
        myarg='default'
    ...

myfun() # zero arguments OK
...
myfun('a string') # one argument OK
...
myfun('a string','an extra string') # two arguments so it should fail here
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#4
yeah you could do that.

>>> def func(arg=None):
...     if not arg:
...             arg = 'default'
...     print(arg)
... 
>>> func()
default
>>> func('test')
test
>>> func('test',2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes from 0 to 1 positional arguments but 2 were given
Recommended Tutorials:
Reply
#5
In [1]: def func(*args):
   ...:     if not args:
   ...:         args = 'default'
   ...:     print(args)
   ...:     

In [2]: func('test')
('test',)

In [3]: func('test', 2)
('test', 2)

In [4]: func()
default
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#6
Not to forget the keyword variant:

def something(**kwargs):
    if kwargs:
        for key, value in kwargs.items():
            print(f'{key} is {value}')
    else:
        print('nothing to see here')
            

something()
something(name="fred")
something(place="London", wetness="raining heavily", temp=10)
Which outputs:
nothing to see here
name is fred
place is London
wetness is raining heavily
temp is 10
You don't have to use *args and **kwargs, it is just convention: *mice and **cats, for example, would work. You can use *args and **kwargs in the same call.
I am trying to help you, really, even if it doesn't always seem that way
Reply
#7
I really don't understand - you have it already:

def foo(arg1='default'):
    print('this is {} value'.format(arg1))

foo() # this will use the default argument
foo('my') # this will use the value supplied
foo('my', 'yours') # this will fail
Output:
this is default value this is my value Traceback (most recent call last): File "/home/boyan/Desktop/test.py", line 6, in <module> foo('my', 'yours') TypeError: foo() takes from 0 to 1 positional arguments but 2 were given
Reply
#8
There is a problem with *args and **kwargs regarding the task.
Skaperen Wrote:to accept zero or one argument
There is no limit for that in *args and **kwargs

Just add:
>>> @limit_args(1)
... def func(*args):
...     if not args:
...         args = 'default'
...     return args

>>> func()
'default'

>>> func('hello')
('hello',)

>>> func('hello', 'world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in new_f
TooManyArguments: 1 args accepted at most, 2 args passed
1 args accepted at most, 2 args passed

>>> @limit_args(1)
... def something(**kwargs):
...     if kwargs:
...         for key, value in kwargs.items():
...             print(f'{key} is {value}')
...     else:
...         print('nothing to see here')

>>> something(place="London")
place is London

>>> something(place="London",  wetness="raining heavily")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in new_f
TooManyArguments: 1 args accepted at most, 0 args passed
1 args accepted at most, 0 args passed
The missing code for that.
class TooManyArguments(Exception):
    pass

def limit_args(n):
    def limit_decorator(func):
        def new_f(*args, **kwargs):
            if len(args or kwarg) > n:
                raise TooManyArguments(f"{n} args accepted at most, {len(args)} args passed")
            return func(*args, **kwargs)
        return new_f
    return limit_decorator
But this going a little overboard,as the simple solution shown solve  that task.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  SyntaxError: positional argument follows keyword argument syd_jat 3 5,736 Mar-03-2020, 08:34 AM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020