[Tutor] *args, **kargs as arguments

wesley chun wescpy at gmail.com
Sat Nov 10 06:16:04 CET 2007


hi, and welcome to Python!!

> class Derived(BaseClass):
>         def __init__(self, *args, **kargs):
>                 BaseClass.__init__(self, *args, **kargs)
>
> - *args, **kargs passes a tuple and a dictionary to the BaseClass constructor.
>
> My assumption is the BaseClass will always have a constructor that will
> be receiving the tuple and a dictionary. Am I right?

not quite.  you're on the right track though. a couple of thoughts.
let's take this question outside of classes for a moment.

1. you are not "receiving" a tuple or dict. rather, any variables
(non-keyworded and keyworded) will be passed to those designated
variables if there are no direct variables corresponding to those
parameters. let's talk about the '*' for a moment.  when placed in a
function signature, it means to accept a variable number of arguments.
 for example:

def foo(x, *rest):
     pass

you can call foo() with one argument only, i.e., foo(123), foo('xxx'),
etc.  but you can also call this argument with any number of
parameters, i.e., foo(123, 'xyz'), foo(3.14, 'xyz', 123), etc.  the
1st argument will be assigned to 'x' while the "rest" of the arguments
get put into the tuple 'rest':  x = 3.14 and rest = ('xyz', 123). if
only 'x' is passed in, the 'rest' is an empty tuple. this differs
from:

def foo(*all):
    pass

in the earlier example, 'x' is required.  in this example, no
parameters are required. foo() is just as good as foo(123), foo(123,
'xyz'), etc.

2. this is not a question you asked, but sometimes people get confused
when '*' is used in function *calls* (vs. signatures as in the above).
when you define a function like this:

def foo(x, y, z):
    pass

you must call foo() with 3 parameters, i.e., foo(12, 'abc', 3.14).
one use of the "*" is to designate its members as parameters to the
called function. the use case comes up when you have a list, say t =
[12, 'abc', 3.14].  to call the function, you would have to do this:
foo(t[0], t[1], t[2]).

now, intuitively, you would naturally ask the question, "can i pass in
the entire list such that all of its elements are assigned to the
individual parameters?"  the answer is "YES:" foo(*t) does the same
thing, but is easier on the programmer, yet does not make the code
significantly more complicated

3. the same arguments above apply to '**', dictionaries, and keyworded
arguments like, foo=123.

4. also not 100%-related to your question:  __init__() is not really a
"constructor" in the true sense.  in Python, the *interpreter* creates
the instance object *for* you, one of the reasons why there is no
"new" keyword.  __init__() is the 1st method that the interpreter
calls after it creates the instance for you.  when you instantiate a
class, you call the class as if it were a function, i.e., Derived().
in the example above with __init__(self, *t, **d), this just means
that this function can take any number of both keyworded or
non-keyworded parameters.

> class BaseClass:
>         def __init__(self, atuple, adict):

this signature differs from __init__(self, *atuple, **adict) because
the former takes exactly 2 arguments (in addition to 'self') while
this latter one can take any number of arguments.

> I also found a construct something like this:
>
> class URLopener:
>         def __init__(self, proxies=None, **x509):

this function potentially takes a single object (assigned to proxies)
and any number of keyworded arguments (which go into the 'x509' dict).

hope this helps!
-- wesley
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"Core Python Programming", Prentice Hall, (c)2007,2001
    http://corepython.com

wesley.j.chun :: wescpy-at-gmail.com
python training and technical consulting
cyberweb.consulting : silicon valley, ca
http://cyberwebconsulting.com


More information about the Tutor mailing list