The Python Oracle

What do *args and **kwargs mean?

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Magical Minnie Puzzles

--

Chapters
00:00 What Do *Args And **Kwargs Mean?
00:28 Accepted Answer Score 282
01:12 Answer 2 Score 98
01:41 Answer 3 Score 75
02:00 Answer 4 Score 26
02:28 Thank you

--

Full question
https://stackoverflow.com/questions/2870...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ACCEPTED ANSWER

Score 282


Putting *args and/or **kwargs as the last items in your function definition’s argument list allows that function to accept an arbitrary number of arguments and/or keyword arguments.

For example, if you wanted to write a function that returned the sum of all its arguments, no matter how many you supply, you could write it like this:

def my_sum(*args):
    return sum(args)

It’s probably more commonly used in object-oriented programming, when you’re overriding a function, and want to call the original function with whatever arguments the user passes in.

You don’t actually have to call them args and kwargs, that’s just a convention. It’s the * and ** that do the magic.

The official Python documentation has a more in-depth look.




ANSWER 2

Score 98


Also, we use them for managing inheritance.

class Super( object ):
   def __init__( self, this, that ):
       self.this = this
       self.that = that

class Sub( Super ):
   def __init__( self, myStuff, *args, **kw ):
       super( Sub, self ).__init__( *args, **kw )
       self.myStuff= myStuff

x= Super( 2.7, 3.1 )
y= Sub( "green", 7, 6 )

This way Sub doesn't really know (or care) what the superclass initialization is. Should you realize that you need to change the superclass, you can fix things without having to sweat the details in each subclass.




ANSWER 3

Score 75


Notice the cool thing in S.Lott's comment - you can also call functions with *mylist and **mydict to unpack positional and keyword arguments:

def foo(a, b, c, d):
  print a, b, c, d

l = [0, 1]
d = {"d":3, "c":2}

foo(*l, **d)

Will print: 0 1 2 3




ANSWER 4

Score 26


Another good use for *args and **kwargs: you can define generic "catch all" functions, which is great for decorators where you return such a wrapper instead of the original function.

An example with a trivial caching decorator:

import pickle, functools
def cache(f):
  _cache = {}
  def wrapper(*args, **kwargs):
    key = pickle.dumps((args, kwargs))
    if key not in _cache:
      _cache[key] = f(*args, **kwargs) # call the wrapped function, save in cache
    return _cache[key] # read value from cache
  functools.update_wrapper(wrapper, f) # update wrapper's metadata
  return wrapper

import time
@cache
def foo(n):
  time.sleep(2)
  return n*2

foo(10) # first call with parameter 10, sleeps
foo(10) # returns immediately