function call - default value & collecting arguments

P

Primoz Skale

Hello!

I am fairly new to Python, so I apologise if this is a 'newbie' question.

First define a simple function:

def f(a=0):
print a
0

Argument a in function f() is set at default value of 0, if it is not passed
to the function at the function call. I get this! :)

I also understand (fairly) how to collect arguments. For example, let's
define another function:

def f(*a):
print a
()

OK, everything allright till so fair. But! :) Now define third function as:

def f(*a):
print a[0]

In this case, function only prints first argument in the tuple:
Traceback (most recent call last):
File "<pyshell#425>", line 1, in <module>
f() #no arguments passed
File "<pyshell#422>", line 2, in f
print a[0]
IndexError: tuple index out of range

Then I tried to define the function as:

def f(*a=(0,)):
print a[0] #this should come next, but we get error msg instead, saying

SyntaxError: invalid syntax

but it does not work this way. Now my 'newbie' question: Why not? :)
I wanted to write function in this way, because then we can call function
without any arguments, and it would still print 0 (in this case).

What I wanted was something like this:

def f(*a=(0,)):
print a[0]
0

but this of course does not work. Again, why not?

Thank you for your comments.

Primoz
 
T

Terry Reedy

| def f(*a=(0,)):
| print a[0] #this should come next, but we get error msg instead, saying
|
| SyntaxError: invalid syntax
|
| but it does not work this way. Now my 'newbie' question: Why not? :)

Possibly because no one ever thought of that.

More likely because it is contradictory: by definition, *a *always* gets a
value, so there is never a need for a 'default'. When a param gets a value
you don't like, you have to explicitly replace it or whatever.

So add at the top 'a = a or (0,)'

tjr
 
B

bruno.desthuilliers

Hello!

I am fairly new to Python, so I apologise if this is a 'newbie' question.

First define a simple function:

def f(a=0):
print a


0

Argument a in function f() is set at default value of 0, if it is not passed
to the function at the function call. I get this! :)

I also understand (fairly) how to collect arguments. For example, let's
define another function:

def f(*a):
print a

This means that f takes any number of optional positional arguments.
If nothing is passed, within f, 'a' will be an empty tuple. Note that
this is *not* the usual way to define a function taking multiple
(mandatory) arguments.
()

OK, everything allright till so fair. But! :) Now define third function as:

def f(*a):
print a[0]

In this case, function only prints first argument in the tuple:

*If* there's one.

IndexError ?

Traceback (most recent call last):
File "<pyshell#425>", line 1, in <module>
f() #no arguments passed
File "<pyshell#422>", line 2, in f
print a[0]
IndexError: tuple index out of range
Bingo.

Then I tried to define the function as:

def f(*a=(0,)):

SyntaxError ?
print a[0] #this should come next, but we get error msg instead, saying

SyntaxError: invalid syntax
Bingo.

but it does not work this way. Now my 'newbie' question: Why not? :)

Condescending answer : "because" !-)
(Sorry, couldn't resist.)

More seriously, I can't tell you why this is not allowed, but :
I wanted to write function in this way, because then we can call function
without any arguments, and it would still print 0 (in this case).

def f(*a):
try:
print a[0]
except IndexError:
print 0

or

def f(*a):
if not a:
a = (0,)
print a[0]

or (slightly more involved, and certainly overkill):

def with_default_args(default):
def decorator(func):
def wrapper(*args):
if not args:
args = default
return func(*args)
return wrapper
return decorator

@with_default_args((0,))
def f(*a):
print a[0]

HTH
 
P

Primoz Skale

I also understand (fairly) how to collect arguments. For example, let's
This means that f takes any number of optional positional arguments.
If nothing is passed, within f, 'a' will be an empty tuple. Note that
this is *not* the usual way to define a function taking multiple
(mandatory) arguments.

M. Lutz in "Learning Python" had defined it this way. What is the *usual*
way in this case?
or (slightly more involved, and certainly overkill):

def with_default_args(default):
def decorator(func):
def wrapper(*args):
if not args:
args = default
return func(*args)
return wrapper
return decorator

@with_default_args((0,))
def f(*a):
print a[0]

Now, this is interesting. Thanks! :)

Primoz
 
B

bruno.desthuilliers

M. Lutz in "Learning Python" had defined it this way. What is the *usual*
way in this case?

You mean : "what's the usual way to define a function taking multiple
*mandatory* arguments" ? I'd think it's explained in your book ???

def f(a, b, c):
print a, b, c

But this is such a cs101 point that we're surely misunderstanding each
other here.
or (slightly more involved, and certainly overkill):
def with_default_args(default):
def decorator(func):
def wrapper(*args):
if not args:
args = default
return func(*args)
return wrapper
return decorator
@with_default_args((0,))
def f(*a):
print a[0]

Now, this is interesting. Thanks! :)

Dont take this as a "recommanded" solution to your problem - it was
(mostly) to be exhaustive (and a bit on the "showing off" side too to
be honest).
 
O

OKB (not okblacke)

Primoz said:
OK, everything allright till so fair. But! :) Now define third
function as:

def f(*a):
print a[0]

In this case, function only prints first argument in the tuple:
Traceback (most recent call last):
File "<pyshell#425>", line 1, in <module>
f() #no arguments passed
File "<pyshell#422>", line 2, in f
print a[0]
IndexError: tuple index out of range

Then I tried to define the function as:

def f(*a=(0,)):
print a[0] #this should come next, but we get error msg instead,
saying

SyntaxError: invalid syntax

but it does not work this way. Now my 'newbie' question: Why not?
:) I wanted to write function in this way, because then we can call
function without any arguments, and it would still print 0 (in this
case).

What I wanted was something like this:

def f(*a=(0,)):
print a[0]

When you use the *a syntax, you're saying that you want a to
contain a tuple of all the arguments. When you try *a=(0,), you seem to
be saying that you want a to hold all the arguments, or, if there are
none, you want to pretend that it was called with one argument, namely
0.

Well, if you want to ensure that there is at least one argument,
and print that first one, and make it zero if it's not supplied, why are
you using the *a syntax? You're clearly treating that first argument
distinctly, since you want to apply a default value to it but not to any
others. Just do this:

def f(a, *b):
print a

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
P

Primoz Skale

You mean : "what's the usual way to define a function taking multiple
*mandatory* arguments" ? I'd think it's explained in your book ???

def f(a, b, c):
print a, b, c

But this is such a cs101 point that we're surely misunderstanding each
other here.

Yes, this was misunderstanding. I thought you meant defining with the *a,
and not with a,b,c, etc....Thanks anyway :)
or (slightly more involved, and certainly overkill):
def with_default_args(default):
def decorator(func):
def wrapper(*args):
if not args:
args = default
return func(*args)
return wrapper
return decorator
@with_default_args((0,))
def f(*a):
print a[0]

Now, this is interesting. Thanks! :)

Dont take this as a "recommanded" solution to your problem - it was
(mostly) to be exhaustive (and a bit on the "showing off" side too to
be honest).

No of course not - but it is interesting...

P.
 
P

Primoz Skale

OKB (not okblacke) said:
Primoz said:
OK, everything allright till so fair. But! :) Now define third
function as:

def f(*a):
print a[0]

In this case, function only prints first argument in the tuple:
f(1,2,3) 1
3
f() #no arguments passed
Traceback (most recent call last):
File "<pyshell#425>", line 1, in <module>
f() #no arguments passed
File "<pyshell#422>", line 2, in f
print a[0]
IndexError: tuple index out of range

Then I tried to define the function as:

def f(*a=(0,)):
print a[0] #this should come next, but we get error msg instead,
saying

SyntaxError: invalid syntax

but it does not work this way. Now my 'newbie' question: Why not?
:) I wanted to write function in this way, because then we can call
function without any arguments, and it would still print 0 (in this
case).

What I wanted was something like this:

def f(*a=(0,)):
print a[0]
f(1,2) 1
f() #no args passed 0

When you use the *a syntax, you're saying that you want a to
contain a tuple of all the arguments. When you try *a=(0,), you seem to
be saying that you want a to hold all the arguments, or, if there are
none, you want to pretend that it was called with one argument, namely
0.

Well, if you want to ensure that there is at least one argument,
and print that first one, and make it zero if it's not supplied, why are
you using the *a syntax? You're clearly treating that first argument
distinctly, since you want to apply a default value to it but not to any
others. Just do this:

def f(a, *b):
print a


Thanks! I never thought of that.... :)

P.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top