473,320 Members | 2,193 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Argument Precedence (possible bug?)

Hello all,

I am just learning Python and have come across something I feel might
be a bug. Please enlightenment me... The following code presents a
challenge. How in the world do you provide an argument for *arg4?

## ================================================== ==========
def argPrecedence(par1, par2=0, par3=0, *par4, **par5):
print 'par1 =', par1, ' # positional argument'
print 'par2 =', par2, ' # keyword argument'
print 'par3 =', par3, ' # keyword argument'
print 'par4 =', par4, ' # argument converted to tuple'
print 'par5 =', par5, ' # argument converted to dictionary'
argPrecedence('arg1', arg3='arg3', arg2='arg2', arg5='arg5')

# argPrecedence Results:
par1 = arg1 # positional argument
par2 = arg2 # keyword argument
par3 = arg3 # keyword argument
par4 = () # argument converted to tuple
par5 = {'arg5': 'arg5'} # argument converted to dictionary
## ================================================== ==========

The code above is verbose with comments because I am just learning
Python and am creating my own examples and reference materials... Can
you solve the problem? If so, can you share the solution? If not, is
this a bug, limitation or is it a feature?

Thank you for your time on this one!

PS. I could be far off with this codes purpose; to try and create an
example that will house all the different possible parameters
(positional, keyword, * and **) in one single def statement.

--
Best Regards
Victor B. Gonzalez

Mar 5 '06 #1
11 1957
Please forgive my call()

Change this:
argPrecedence('arg1', arg3='arg3', arg2='arg2', arg5='arg5')

to this:
argPrecedence('arg1', par3='arg3', par2='arg2', arg5='arg5')

Thanks!

Mar 5 '06 #2
Hello all,

I am just learning Python and have come across something I feel might
be a bug. Please enlightenment me... The following code presents a
challenge. How in the world do you provide an argument for *arg4?

## ================================================== ==========
def argPrecedence(par1, par2=0, par3=0, *par4, **par5):
print 'par1 =', par1, ' # positional argument'
print 'par2 =', par2, ' # keyword argument'
print 'par3 =', par3, ' # keyword argument'
print 'par4 =', par4, ' # argument converted to tuple'
print 'par5 =', par5, ' # argument converted to dictionary'

argPrecedence('arg1', par3='arg3', par2='arg2', arg5='arg5')

# argPrecedence Results:
par1 = arg1 # positional argument
par2 = arg2 # keyword argument
par3 = arg3 # keyword argument
par4 = () # argument converted to tuple
par5 = {'arg5': 'arg5'} # argument converted to dictionary
## ================================================== ==========

The code above is verbose with comments because I am just learning
Python and am creating my own examples and reference materials... Can
you solve the problem? If so, can you share the solution? If not, is
this a bug, limitation or is it a feature?

Thank you for your time on this one!

PS. I could be far off with this codes purpose; to try and create an
example that will house all the different possible parameters
(positional, keyword, * and **) in one single def statement.

--
Best Regards
Victor B. Gonzalez

Mar 5 '06 #3
"vbgunz" wrote:
I am just learning Python and have come across something I feel might
be a bug. Please enlightenment me... The following code presents a
challenge. How in the world do you provide an argument for *arg4?

## ================================================== ==========
def argPrecedence(par1, par2=0, par3=0, *par4, **par5):
print 'par1 =', par1, ' # positional argument'
print 'par2 =', par2, ' # keyword argument'
print 'par3 =', par3, ' # keyword argument'
print 'par4 =', par4, ' # argument converted to tuple'
print 'par5 =', par5, ' # argument converted to dictionary'

argPrecedence('arg1', arg3='arg3', arg2='arg2', arg5='arg5')

# argPrecedence Results:
par1 = arg1 # positional argument
par2 = arg2 # keyword argument
par3 = arg3 # keyword argument
par4 = () # argument converted to tuple
par5 = {'arg5': 'arg5'} # argument converted to dictionary
## ================================================== ==========

The code above is verbose with comments because I am just learning
Python and am creating my own examples and reference materials... Can
you solve the problem? If so, can you share the solution? If not, is
this a bug, limitation or is it a feature?


not sure what you think the bug is, but I suspect that you've completely
missed the point of what * and ** do, and how they're used in real code.

</F>

Mar 5 '06 #4
vbgunz wrote:
I am just learning Python and have come across something I feel might
be a bug. Please enlightenment me... The following code presents a
challenge. How in the world do you provide an argument for *arg4?


Maybe by putting that in the list of arguments? ...

You don't even *have* an arg4 in the list, so how are we supposed to
know what you are asking without guessing? Please consider rephrasing
the question.

-Peter

Mar 5 '06 #5
On Sun, 05 Mar 2006 04:45:05 -0800, vbgunz wrote:
Hello all,

I am just learning Python and have come across something I feel might
be a bug. Please enlightenment me... The following code presents a
challenge. How in the world do you provide an argument for *arg4?

## ================================================== ==========
def argPrecedence(par1, par2=0, par3=0, *par4, **par5):
print 'par1 =', par1, ' # positional argument'
print 'par2 =', par2, ' # keyword argument'
print 'par3 =', par3, ' # keyword argument'
print 'par4 =', par4, ' # argument converted to tuple'
print 'par5 =', par5, ' # argument converted to dictionary'


No, you are confused about * and ** arguments. They don't convert
arguments, they collect them.

def f(a, b=0, *args, **kwargs):
print "a =", a
print "b =", b
print "args =", args
print "kwargs =", kwargs

Now call the function different ways, and see which will work and which
won't.

f(1)
f(1, 2)
f(1, b=2)
f(a=1, b=2)
f(b=2, a=1)

Notice that this does not work:

f(b=3)

Do you understand why not?

Now look at these calls:

f(1, 2, 3)
f(1, 2, 3, 4, 5, 6)
f(1, 2, 3, 4, 5, 6, foo=7, bar=8)

In the function definition f(a, b=0, *args, **kwargs), a must be supplied,
b has a default value so it can be left out. Both a and b can be provided
as positional arguments like f(2, 3) or as keyword arguments.

Any _extra_ positional arguments are collected into a tuple called args,
and any _extra_ keyword arguments are collected into a dictionary called
kwargs. Of course you can use any names you like.

Hope this helps,

--
Steven.

Mar 5 '06 #6
On Sun, 05 Mar 2006 04:45:05 -0800, vbgunz wrote:
PS. I could be far off with this codes purpose; to try and create an
example that will house all the different possible parameters
(positional, keyword, * and **) in one single def statement.


This is usually a bad idea, not because Python can't cope with it, but
because it is usually better to learn new things in small pieces, not one
giant enormous piece.

Try creating a number of small functions that do different things:

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

def g(a=0, b=0, c=0):
print "a =", a, "b =", b, "c =", c

Now call them different ways, and see what happens:

f()
f(1)
f(1,2)
f(1,2,3)
f(b=2)

Can you see a pattern?

g()
g(1)
g(1,2)
g(1,2,3)
g(b=2)

Then move on to argument collectors:

def h(a, b, c=0, *d, **e):
print "a =", a, "b =", b, "c =", c
print "d =", d, "e =", e

Also, remember that "positional arguments" and "keyword arguments" aren't
defined differently, they are given when you call the function. For
example, suppose you have this:

def function(x, y):
print x + y

Now you call it with positional arguments: function(3, 7)
Now you call it with keyword arguments: function(x=3, y=7)
Now you call it with both: function(3, y=7)

All from the same definition. An argument is positional or keyword
according to how it is given, not how it is defined.
--
Steven.

Mar 5 '06 #7
I am sorry I hung you up on a typo Peter Hansen. On line 5 *arg4 should
have been *par4. I hope it makes complete sense now. Sorry.

Mar 5 '06 #8
Please allow me some time to look at your examples. I get hung up over
the smallest details because in my mind, my approach should have just
worked... I learned about these parameters reading "O'reilly Learning
Python 2nd Edition". On page 217 of the paperback or Chapter 13.5.6 in
the ebook, topic: 'Argument matching: The Gritty Details' mentions the
following in verbatim...

....'''
Moreover, Python internally carries out the following steps to match
arguments before assignment:
1. Assign non-keyword arguments by position.
2. Assign keyword arguments by matching names.
3. Assign extra non-keyword arguments to *name tuple.
4. Assign extra keyword arguments to **name dictionary.
5. Assign default values to unassigned arguments in header.
'''...

As you can probably tell, I tried to follow the steps exactly, except
step 5 got me lost so I tried not to question it. Anyhow, thank you
very much for your time and examples. I will get back to you as soon as
I am done putting your response to trial. Thank you!

Mar 5 '06 #9

"vbgunz" <vb****@gmail.com> wrote in message
news:11*********************@i40g2000cwc.googlegro ups.com...
Hello all,

I am just learning Python and have come across something I feel might
be a bug.
I feel it is more likely that there in a bug in the communication process
from the manual to you, on an admittedly somewhat confusing and complex
subject.
Please enlightenment me...
OK. Here is my attempt at a summary.

The parameters for a function are the local variable names listed in the
definition header in ()s after the function name. There may be any number
of regular parameters and up to two collection parameters.

The arguments for a function call are the objects listed in ()s after the
function object (usually but not necessarily indicated by name).
Argument objects are the result of evaluating an expression.
An argument is optionally named by prefixing the expression with 'name=',
with the restriction that all args after a named arg must also be named.

Regular paramenter names (and slots of collection parameters) are bound to
argument objects by position or name according to the rules given in the
manual. At the end of the process, all parameters and arguments must
exactly one binding. (For parameters, the binding may be a default given
in the definition.) If not, an exception is raised and the call aborted.
How in the world do you provide an argument for *arg4?
You obviously mean par4. See below for how it gets a non-empty value.
def argPrecedence(par1, par2=0, par3=0, *par4, **par5):
Par1, par2, and par3 are regular parameters. They can by matched either by
position or name on a per-call basis. Mixing position and name matching in
any one call is strongly discouraged as confusing and error prone.

Par2 and par3 have default arg objects (calculated when the function is
defined). That only means that they do not have to match any of the args
in a particular call. It does not determine whether the binding to
explicit args in a particular call will be by position or name.
print 'par1 =', par1, ' # positional argument'
print 'par2 =', par2, ' # keyword argument'
print 'par3 =', par3, ' # keyword argument'
So these comments are wrong except as they happen to be right for a
particular call.
Par4 and par5 are leftover-argument collection objects bound by default to
() and {} respectively if there are, respectively, no leftover positional
or named args. So the way to get a nonempty tuple bound to par4 is to have
a leftover positional arg which requires that you give at least 4 (since
the first three will be bound to the three regular parameters).
print 'par4 =', par4, ' # argument converted to tuple'
print 'par5 =', par5, ' # argument converted to dictionary'
Wrong. Leftover args are placed in, not individually converted to, a tuple
or dictionary.
PS. I could be far off with this codes purpose; to try and create an
example that will house all the different possible parameters
(positional, keyword, * and **) in one single def statement.


Again, regular parameters are both positional and named, and the matching
on any particular call can be either (subject to the positional, then named
args restriction). In any case, what I think you mean above is not
possible. As stated previously, the *leftover_pos_arg tuple will be
nonempty only if all regular params are positionally matched.

Terry Jan Reedy

Mar 5 '06 #10
Hello, Steven D'Aprano, Terry Jan Reedy!

I would really like to extend my thanks to you guys. I hope I've got it
right this time!

def posKeyArgs(a, b=2, c=3):
print a, b, c

#posKeyArgs(b=20) # too few positional arguments. a needs an arg.
#posKeyArgs(10, c=30, 20) # pos_args cannot follow any kw_args.

def specialArgs(*args, **kwargs): # Can't call these keywords!
print args
print kwargs

specialArgs(args='arg1', kwargs='kwargs') # Keywords match nothing.
specialArgs('string') # not converted. Collected into: ('string',)

The above can begin to explain why I had problems with my first
example. *args and **kwargs cannot have arguments assigned to them by
keyword. Once an argument is matched by keyword, all following
arguments must also be matched by keyword.

This would explain why using only positional arguments, my first
example would have worked right out of the box. Because, all
positionals would have matched first, then all left overs would have
been collected into *args, then finally any keyword args would be
collected into **kwargs.

So far the general consensus also seems to be not to over complicate a
function definition with such parameters. This makes sense and is why I
chose Python over many other options. I love the idea of explicit over
implicit :) Again though, my first example was only a personal
reference.

Fellas, thank you all so much for helping me understand this much
better. You guys are my angels of Python for sure!

Mar 6 '06 #11

"vbgunz" <vb****@gmail.com> wrote in message
news:11**********************@v46g2000cwv.googlegr oups.com...
Hello, Steven D'Aprano, Terry Jan Reedy!

I would really like to extend my thanks to you guys. I hope I've got it
right this time!

def posKeyArgs(a, b=2, c=3):
print a, b, c

#posKeyArgs(b=20) # too few positional arguments. a needs an arg.
Yes, parameter a must get bound to something.
Any of pKA(10, b=20), pKA(a=10,b=20), pKA(c=30,a=5), etc, should work.
#posKeyArgs(10, c=30, 20) # pos_args cannot follow any kw_args.


Yes, this is an extreme of flexibility not allowed.

Terry Jan Reedy

Mar 7 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

20
by: Vivek N | last post by:
Hi Folks, This question may well have been asked and answered before. But, sorry that I couldn't find one from the archives. I typed up this program and compiled it with gcc 3.3.2 main() { int...
25
by: noe | last post by:
Hello, I'm writing a file system filter driver and I've found in an example this sentence: if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoRead )) { return...
21
by: siliconwafer | last post by:
Hi, In case of following expression: c = a && --b; if a is 0,b is not evaluated and c directly becomes 0. Does this mean that && operator is given a higher precedence over '--'operator? as...
11
by: Rupesh | last post by:
Hello all, See the code .... int i=-3,j=2,k=0,m; m=++i;&&++j||++k; printf ("%d %d %d %d",i,j,k,m); I executed this code on gcc. the o/p i had got is:- -2 3 0 1
0
by: vbgunz | last post by:
Hello all, I am just learning Python and have come across something I feel might be a bug. Please enlightenment me... The following code presents a challenge. How in the world do you provide an...
5
by: junky_fellow | last post by:
Hi, I have a very basic doubt about associativity and precedence of operators. I am not a computer science person and may find it quite weird. Consider an expression 4+5*2
9
by: marko | last post by:
/* code start */ int a = 0; /* expected evaluation and excution order with precedence in mind /* False(3) , True(1), False(2) */ if ( (a=1) == 0 || 0 != 1 && (a =2) == 1) putchar('T');...
32
by: silpau | last post by:
hi, i am a bit confused on expression evaluation order in expressions involving unary increment.decrement operators along with binary operators. For example in the following expression x...
5
by: Peng Yu | last post by:
Hi, Please see the following code and the output. It seems that if one of %'s oprand is unsigned, the other will also be converted to unsigned. There is a operator precedence table in...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.