[Tutor] Defining variable arguments in a function in python

Karthik Bhat bhatkarthik1996 at gmail.com
Sun Dec 30 04:54:36 EST 2018


Thank you all for the quick response!

On Sun, Dec 30, 2018 at 10:39 AM Avi Gross <avigross at verizon.net> wrote:

> I have my usual off the wall answer.
>
> OK, seriously. Not exactly an answer but perhaps an experiment.
>
> The question was how to have a non-named first argument to a function with
> some form of default.
>
> As was pointed out, this does not fit well with being able to have python
> gather all positional arguments after it as well as all keyword arguments.
>
> But bear with me. Say I want to have a way to signal that I want a default
> for the first argument?
>
> An empty comma fails but try this:
>
> def hello(a, *n, **m) :
>         if a == None: a=5
>         print(a)
>         print(*n)
>         print(**m)
>
> The above says "a" is required. It can be followed by any number of
> positional args gathered into "n" and any number of keyword args gathered
> into "m"
>
> But what if you define a sentinel to watch for such as None, in the above?
>
> If the first and only arg is None, it switches to the default of 5.
>
> >>> hello(None)
> 5
>
> Add a few more args and it properly takes it.
>
> >>> hello(1,2,3)
> 1
> 2 3
>
> Switch the first to None:
>
> >>> hello(None,2,3)
> 5
> 2 3
>
> The keywords don't work for print but no biggie.
>
> But is this only for None? What I say any negative arg is replaced by 5?
>
> def hello(a, *n, **m) :
>         if a < 0: a=5
>         print(a)
>         print(*n)
>
> Seems to work fine:
>
> >>> hello(-666, 2, 3, 4)
> 5
> 2 3 4
>
> And I wonder if we can use the darn ellipsis for something useful?
>
> def hello(a, *n, **m) :
>         if a == ... : a=5
>         print(a)
>         print(*n)
>
> >>> hello(1,2,3)
> 1
> 2 3
> >>> hello(...,2,3)
> 5
> 2 3
> >>> hello(...,2,...)
> 5
> 2 Ellipsis
>
> OK, all kidding aside, is this helpful? I mean if you want a function where
> you MUST give at least one arg and specify the first arg can be some odd
> choice (as above) and then be replaced by  a default perhaps it would be
> tolerable to use None or an Ellipsis.
>
> Or on a more practical level, say a function wants an input from 1 to 10.
> The if statement above can be something like:
>
> >>> def hello(a, *n, **m) :
>         if not (1 <= a <= 10) : a=5
>         print(a)
>         print(*n)
>
>
> >>> hello(1,2,3)
> 1
> 2 3
> >>> hello(21,2,3)
> 5
> 2 3
> >>> hello(-5,2,3)
> 5
> 2 3
> >>> hello("infinity and beyond",2,3)
> Traceback (most recent call last):
>   File "<pyshell#32>", line 1, in <module>
>     hello("infinity and beyond",2,3)
>   File "<pyshell#28>", line 2, in hello
>     if not (1 <= a <= 10) : a=5
> TypeError: '<=' not supported between instances of 'int' and 'str'
>
> As expected, it may take a bit more code such as checking if you got an int
> but the idea may be solid enough. It is NOT the same as having a default
> from the command line but it may satisfy some need.
>
> Other than that, I fully agree that the current python spec cannot support
> anything like this in the function definition.
>
> Side note: To spare others, I sent Steven alone a deeper reply about ways
> to
> select random rows from a pandas DataFrame. I am still learning how pandas
> works and doubt many others here have any immediate needs.
>
>
>
>
>
>
>
>
>
> -----Original Message-----
> From: Tutor <tutor-bounces+avigross=verizon.net at python.org> On Behalf Of
> Steven D'Aprano
> Sent: Saturday, December 29, 2018 6:02 AM
> To: tutor at python.org
> Subject: Re: [Tutor] Defining variable arguments in a function in python
>
> On Sat, Dec 29, 2018 at 11:42:16AM +0530, Karthik Bhat wrote:
> > Hello,
> >
> >         I have the following piece of code. In this, I wanted to make
> > use of the optional parameter given to 'a', i.e- '5', and not '1'
> >
> > def fun_varargs(a=5, *numbers, **dict):
> [...]
> >
> > fun_varargs(1,2,3,4,5,6,7,8,9,10,Jack=111,John=222,Jimmy=333)
> >
> > How do I make the tuple 'number' contain the first element to be 1 and
> not
> 2?
>
>
> You can't. Python allocates positional arguments like "a" first, and only
> then collects whatever is left over in *numbers. How else would you expect
> it to work? Suppose you called:
>
> fun_varargs(1, 2, 3)
>
> wanting a to get the value 1, and numbers to get the values (2, 3). And
> then
> immediately after that you call
>
> fun_varargs(1, 2, 3)
>
> wanting a to get the default value 5 and numbers to get the values (1, 2,
> 3). How is the interpreter supposed to guess which one you wanted?
>
> If you can think of a way to resolve the question of when to give "a"
> the default value, then we can help you program it yourself:
>
>
> def func(*args, **kwargs):
>     if condition:
>         # When?
>         a = args[0]
>         numbers = args[1:]
>     else:
>         a = 5  # Default.
>         numbers = args
>     ...
>
> But writing that test "condition" is the hard part.
>
>
>
>
> --
> Steve
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
>


-- 
Regards,
Karthik A Bhat


More information about the Tutor mailing list