Farm Development

What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

Inspired by Titus' blog post about Python's elusive at sign I thought I'd drop a little google egg for anyone who is learning Python and hasn't read the manual cover to cover yet (like I did ... yeah, right).

If you see a def in python with asterisks (or stars), like so:

def foo(*args, **kw):
    pass

...what does this syntax do? It is buried in the Python tutorial here, under More On Defining Functions > Arbitrary Argument Lists which would only appear in a google search if you already knew what the syntax does! The first form means any arbitrary number of arguments to the function foo will be provided to you in a tuple named args. And the second form means any arbitrary number of keyword arguments will be available in the dict kw. For example:

>>> def checkout(*items, **coupons):
...     print items
...     print coupons
... 
>>> checkout('eggs', 'cheese', 'cereal', 
...          cereal='10% off', cheese='buy 1 get 1')
('eggs', 'cheese', 'cereal')
{'cheese': 'buy 1 get 1', 'cereal': '10% off'}
>>> 

The above section in the tutorial has the details on the order in which this is achieved.

DISCLAIMER: The author of this post does not condone lazily learning a programming language by trial and error, reading other peoples' code, or simply googling for an answer to something :)

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    One thing which I've always been unsure of is what the * operator does in the following context

    a = range(0,5)

    b = range(6,10)

    z = zip(a,b)

    zip(*z)

    This has always struck me as odd, because if I simply type

    *z

    in the interpreter, I get a SyntaxError.

    So, what am I passing to zip?

    Cheers,

    -T

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    Yes, it is pretty strange that you can't type *z into the interpretter and see the result, I assume it is due to python internals and how it probably collides with star for multiplication.

    All you are doing by calling zip(*z) is inverting the behavior of def zip(*z): [inside of function]. Behind the scenes, python is actually calling the zip() method like so:

    zip((0, 6), (1, 7), (2, 8), (3, 9))

    in other words, it takes the list or iterable, z, and expands each item to be a separate argument for the function call. I dug through some code and found this as a practical example:

    clauses = [ Files.c.type.id==video_type.id ]

    if time is not None:

    clauses.append(Files.c.modified >= time)

    files = Files.select(and_(*clauses))

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    Thanks for that explanation, it makes sense. I always wondered.

    -T

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    Succinct.

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    > Yes, it is pretty strange that you can't type *z into the interpretter and see the result

    And what would that result be? ;)

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    > Yes, it is pretty strange that you can't type *z into the interpretter and see the result

    *z is function calling syntax, not expression syntax, so you need to use it in an calling context. to see it in action, enter

    def f(*args, **kw): print args, kw

    and then try calling the f() function in different ways (e.g. f(*z) etc).

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    @Esteban :

    >> Yes, it is pretty strange that you can't type *z into the interpretter and see the result

    >

    > And what would that result be? ;)

    actually ... yeah thinking about it again it would make no sense! if z is a list then in an interactive terminal *z would be, errm, a list.

    My knee-jerk response was really to the fact that to find out what zip(*z) is doing, you'd have to write your own zip method to simulate the scenario, which is slightly unintuitive to someone learning python through the terminal.

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    I *never* used Python, I don't have *any* book about it, but I still know what this syntax means, simply because I read the entire tutorial :p. Well, OK, the tutorial is very long, and is referred to as the manual on this page, but still.

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    This was very helpful and I found it on google as you intended :) Just saying thanks.

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    Whew! I'm glad my googling skills were good enough to find this article. Those asterisks were really bugging me to find out the meaning. Now I can sleep (and code) in peace. Thanks!

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    Very helpful, thank you.

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    thx, very helpful indeed.

    (keeping it alive)

    :)

  • Re: What does the def-star-variable (or def-asterisk-parameter) syntax do in Python?

    The core idea behind the * syntax is simple: It unwraps the outermost layer of a list and returns its contents. For example for L = ['eggs', 'cheese', 'cereal'], *L = 'eggs', 'cheese', 'cereal' , the outer [brackets] are removed, and the contents of the list are returned. This is syntactically related to the use of the * in c/c++ for dereferencing an array, i.e. for float a[10], *a is the address of its first element, treating that element as an individual item, rather than a member of the list.

    For the zip example above, z = zip(a, b) gives [(0, 6), (1, 7), (2, 8), (3, 9)], so *z = (0, 6), (1, 7), (2, 8), (3, 9)

    This value can't be returned at the command prompt because it is really a list of results, and thus more properly expressed as [(0, 6), (1, 7), (2, 8), (3, 9)], although as an argument to a function it just "pretends" that the elements of the list come in individually, unwrapped from the list.

Note: HTML tags will be stripped. Hit enter twice for a new paragraph.

Recent Projects

  • JSTestNet

    Like botnet but for JS tests in CI.

  • Nose Nicedots

    Nose plugin that prints nicer dots.

  • Fudge

    Mock objects for testing.

  • Fixture

    Loading and referencing test data.

  • NoseJS

    Nose plugin that runs JavaScript tests for a Python project.

  • Wikir

    converts reST to various Wiki formats.