[Tutor] Don't understand this class/constructor call syntax

Steven D'Aprano steve at pearwood.info
Sat Jul 23 05:09:07 CEST 2011


dave wrote:

> class transmit_path(gr.top_block)
[...]
>         self.packet_transmitter = ieee802_15_4_pkt.ieee802_15_4_mod_pkts(self,
>                                   spb=self._spb, msgq_limit=2)


This calls the ieee802_15_4_mod_pkts initializer (not a constructor -- 
see below) with one positional argument and two keyword arguments.

The positional argument is "self", that is, the transmit_path instance.

The keyword arguments are called spb and msgq_limit; spb is set to the 
value of self._spb, and msgq_limit is set to 2.

The reason I say this is an initializer and not a constructor is that 
Python treats the two as different. The constructor that creates the 
instance is called __new__ not __init__. When __init__ is called, the 
instance has already been constructed, and is now being initialized. The 
reason for this is mostly historical, although it is useful.

(Disclaimer -- so called "old style" or "classic" classes don't have a 
__new__ method, and you cannot customize the actual creation of the 
instance, only the initialization.)

Looking at the ieee802_15_4_mod_pkts initializer:


> class ieee802_15_4_mod_pkts(gr.hier_block2):
>     def __init__(self, pad_for_usrp=True, *args, **kwargs):[/code]

As a method, this takes the instance as first argument (called "self"), 
plus one named argument "pad_for_usrp", an arbitrary number of unnamed 
positional arguments collected into "args", and an arbitrary number of 
named keyword arguments collected into "kwargs".

(Note that args and kwargs are conventions. You could call them anything 
you like -- the "magic", so to speak, comes from the leading * and ** 
and not from the names.)

Given the call:

ieee802_15_4_mod_pkts(self, spb=self._spb, msgq_limit=2)

this corresponds to the initializer receiving arguments:

self = the freshly created ieee802_15_4_mod_pkts instance
pad_for_usrp = the transmit_path instance doing the calling
args = an empty tuple (no positional arguments collect)
kwargs = a dictionary of keyword arguments
          {'spb': value of _spb of the transmit_path instance,
           'msgq_limit': 2}


> What I don't understand is the call to the constructor and the constructor
> definition.  Since it's using a number of advanced features, I'm having
> trouble looking it all up in documentation.
> 
> What does it mean to call with spb=self._spb?  In the example file, spb is set
> = to 2 and so is self._spb.  Is it a sort of pass by reference like C while
> also assigning a value? Why the  ** on kwargs then? as if it is a matrix

No, this is nothing to do with pass by reference, or pass by value 
either. This often confuses people coming to Python from some other 
languages, and if it isn't a FAQ it ought to be. You can read one of my 
posts on this here:

http://www.mail-archive.com/tutor%40python.org/msg46612.html

and the Wikipedia article:

http://en.wikipedia.org/wiki/Evaluation_strategy


What it means is that the method being called (in this case, 
ieee802_15_4_mod_pkts.__init__) sees a keyword argument called "spb". 
This keyword argument has name "spb", and value whatever self._spb has 
at the time it is called.

When Python allocates arguments to the named parameters in a method or 
function, its basic process is roughly something like this:


(1) for methods, automatically assign the instance being called to the 
first named parameter (usually called "self" by convention);

(2) take each positional argument from the caller and assign it to the 
remaining positional parameters, from left to right;

(3) assign any keyword arguments, raising an error if it duplicates a 
value already seen;

(4) raise an error if any unassigned parameter doesn't have a default value;

(5) collect any left over positional arguments into the *args parameter;

(6) collect any left over keyword arguments into the **kwargs parameter.



> (and does anyone have any idea what kwargs are (as opposed to args)?)


Positional arguments: function(1, 2)
Keyword arguments: function(a=1, b=2)



> I'm uncertain about the first argument, but I guess it must be the
> transmit_path object passed in place of the usually implicit self...  I'm just
> not sure how Python figures out that it's not pad_for_usrp... magic I guess!

I don't think that it is used as the implicit self. I think it is the 
pad_for_usrp.




-- 
Steven



More information about the Tutor mailing list