[Tutor] working with time spans ?

Tim Peters tim.one at comcast.net
Sat Jun 5 00:06:30 EDT 2004

[Tim, switches Michele's class to use plain tuples]
>> ...

[Michele Alzetta]
> Yes, but this can contain any tuple, which means I can't extract
> self.startime and feed it in to one of the time functions if I ever
> wanted to.

Good -- you're thinking ahead.  Your objection goes away with the next step
(moving to datetime objects), and simplifying the code to get back to tuples
was a step toward that end.  Making code hairier instead is often a step in
a wrong direction!

[and then to switch from tuples to datetime objects ...]
>> For example, just replace the first 4 lines above with:
>> from datetime import datetime
>> class TimeSpan(object):
>>     def __init__(self, startimetuple, endtimetuple):
>>         self.starttime = datetime(*startimetuple)
>>         self.endtime = datetime(*endtimetuple)

> Er ... what on earth does the "*" in *startimetuple mean ?


is a shortcut for

    apply(f, args)

and you can read about apply() in the Library Reference Manual (in the
section on builtin functions).

If you want to pass a variable number of arguments to a function, you define
the function with this syntax:

    def f(*args):
        print args

Then all the arguments in a call to f() are gathered into a tuple (the "*"
in front of "args" *tells* Python to gather them into a tuple):

>>> f()
>>> f(1)
>>> f("two", "args")
('two', 'args')
>>> f("and", 3, "args")
('and', 3, 'args')

etc.  On the *calling* side, "*something" in an argument list is a bit like
the reverse of that:  it takes the elements of the sequence "something", and
breaks them into out into individual arguments.

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


>>> g(*())
1 2 3
>>> g(*(10,))
10 2 3
>>> g(*(10, 11))
10 11 3
>>> g(*(10, 11, 12))
10 11 12
>>> g(*(10, 11, 12, 13))
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: g() takes at most 3 arguments (4 given)

The datetime.datetime() constructor requires at least 3 arguments, but
accepts as many as 8 (see the docs).  If you already have a tuple in the
right form, it's much easier to use * than to break the tuple apart by hand:

>>> ymd = 2004, 12, 31
>>> print datetime(ymd[0], ymd[1], ymd[2])  # yuck!
2004-12-31 00:00:00
>>> print datetime(*ymd)  # easier and exactly the same thing
2004-12-31 00:00:00
>>> print datetime(ymd)   # not at all the same thing
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: function takes at least 3 arguments (1 given)

Using the * trick on the call side also lets you not care whether the tuple
contains just (year, month, day), or also contains hours and possibly also
minutes and possibly also seconds, etc.  *something breaks them all out, no
matter what len(something) is.

More information about the Tutor mailing list