473,378 Members | 1,393 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,378 software developers and data experts.

args v. *args passed to: os.path.join()

This quest for understanding started very innocently...

A simple error on my part, passing on args as "args" instead of "*args" to
os.path.join() led me to wonder why an error wasn't raised...

def foo(*args):
...
return os.path.join(*args)

foo('a','b') # returns 'a/b'

With: return os.path.join(args)

foo('a','b') # returns ('a', 'b') (unchanged -- no error)

Replacing the 'return's in the function with each print below in turn
produced the results in the comments:

# without '*'
print args # ('a', 'b')
print (args) # ('a', 'b')
print "/".join(args) # a/b
print string.join(args,"/") # a/b
print os.path.join(args) # ('a', 'b')

# with '*'
print *args # syntax error at *
print (*args) # syntax error at *
print "/".join(*args) # TypeError
print string.join(*args,"/") # syntax error at 2nd (")
print os.path.join(*args) # a/b

The results in matrix form (numbers refer to order of print statements):

args *args
1 ('a', 'b') syntax error
2 ('a', 'b') syntax error
3 a/b TypeError
4 a/b syntax error
5 ('a', 'b') a/b

os.path.join() is the only one in this list which doesn't return an error.
Also, os.path.join()'s results are reversed relative to the others by
requiring *args...

My question is: other than discovering this anomaly (and wrong result) at
runtime, is there a simple rule for when to pass on '*args' v. 'args' that
I've somehow missed...?

Thanks,
Pierre
Jul 18 '05 #1
2 2723
Before applying args or *args to a real world sample, lets see what each of
them does:
def testfunc(*args): .... print args
....

Define a function called testfunc, for which all positional arguments are
stored to the tuple args. The body of this functions contains a single
statement which prints this tuple to screen.
testfunc([1,2,3]) ([1, 2, 3],)

The tuple which is printed to screen is the following: a tuple with a single
item which is a list which contains the elements 1, 2 and 3 in this order.
testfunc(*[1,2,3]) (1, 2, 3)

The tuple which is printed to screen is the following: a tuple with the items
1, 2 and 3 in this order.

See where we're heading at? Let's see another example.
def testfunc2(a,b): .... print a
.... print b
....

Lets define another function which takes two arguments (a, b) and prints them
out in order.
testfunc2([1,2]) Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: testfunc2() takes exactly 2 arguments (1 given)

Lets call this function with a single argument (a list, which contains the two
items). The interpreter duly complains that the function takes two arguments,
but only one is given, and raises a TypeError.
testfunc2(*[1,2])

1
2

Again, using the star syntax: We pass two arguments (because the list which is
starred contains two arguments), and these end up in a and b, respectively.

So, what does the star-operator do? It splits up an iterable (a list in this
case) and fills the first len(iterable) positional arguments with the values
it got from the list.

This is why you see different behavior when passing a star or not. Let's look
at the documentation for os.path.join:

join(a, *p)
Join two or more pathname components, inserting '/' as needed

This means that you have to pass at least one argument (a), which is the path
base, and may pass more arguments (*p) which are joined with this item,
inserting slashes as needed.

Now, when you call:

os.path.join(["a","b"])

the list ends up in the a parameter, and because the function doesn't have to
do anything (there are no more arguments), the list is returned unchanged
(although this should probably raise a TypeError, anyone?).

But when you call:

os.path.join(*["a","b"])

the first item of the list ends up as parameter a to the function, the second
item of the list ends up as the second parameter to the function, which are
then duly joined by the function.

And one more look why "".join(*["a","b"]) raises an error:

join(...)
S.join(sequence) -> string

Return a string which is the concatenation of the strings in the
sequence. The separator between elements is S.

The documentation for str.join() states that you pass it one parameter, a
sequence.

Now, when you do "".join(*["a","b"]), the number of passed parameters is two,
and because the function only accepts one parameter, a sequence, the function
call raises an Exception.

HTH!

Heiko.
Jul 18 '05 #2
On Sat, 18 Sep 2004 20:08:35 +0200 Heiko wrote:
Now, when you call:

os.path.join(["a","b"])

the list ends up in the a parameter, and because the function doesn't
have to do anything (there are no more arguments), the list is returned
unchanged (although this should probably raise a TypeError, anyone?).

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ =======

That was the whole point; the rest was pretty much my understanding too...
I can't think of any reason why os.path.join() should ever be presented
anything but strings... on the other hand, maybe it could
check for lists/tuples and use those to return the expected "a/b"...

Then again, I just checked a number of functions in os and os.path;
os.path.join() seems to be the only one which fails to return a
TypeError...

Jul 18 '05 #3

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

Similar topics

70
by: Michael Hoffman | last post by:
Many of you are familiar with Jason Orendorff's path module <http://www.jorendorff.com/articles/python/path/>, which is frequently recommended here on c.l.p. I submitted an RFE to add it to the...
5
by: lkrubner | last post by:
Is it true that Javascript has no clone() method, to pass an object by copy of value instead of reference? If I have an object and want to make an array out of all of its instance variables, I...
1
by: john conwell | last post by:
I've got a process engine written in .Net. the user writes a data file and saves it as file type ".xyz". I have a file assiciation set up in the database that when a .xyz file is invoked (double...
2
by: paul | last post by:
I have a file type that is going to be associated with my visual basic application and i want the user to be able to double click on a file of said type and have it launch the program and load the...
1
by: Steve | last post by:
I have been trying to find documentation on the behavior Can anyone tell me why the first example works and the second doesn't and where I can read about it in the language reference? Steve ...
2
by: goodnamesalltaken | last post by:
Hello fellow python users, I've been working on a basic implementation of a privilege separated web server, and I've goto the point of running a basic cgi script. Basically when the execCGI...
42
by: Holger | last post by:
Hi guys Tried searching for a solution to this, but the error message is so generic, that I could not get any meaningfull results. Anyways - errormessage:...
1
by: jakebbohio | last post by:
I have a user-defined XPath function implemented using a custom context and the IXsltContextFunction interface. For its arguments, it accepts 3: { XPathResultType.Any, XPathResultType.Any,...
8
by: kj | last post by:
How can a script know its absolute path? (__file__ only gives the path it was used to invoke the script.) Basically, I'm looking for the Python equivalent of Perl's FindBin. The point of all...
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...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.