How to explain exactly what "def" does?

holger krekel pyth at devel.trillke.net
Mon Feb 3 15:28:07 EST 2003


Roy Smith wrote:
> While explaining the basics of Python to somebody who's brain had been
> corrupted by Perl as a first language, I came upon an interesting
> wrinkle.  We were talking about containers and names and dynamic
> vs. static typing when I gave the following demo:
> 
> ----------------------------------
> >>> def foo():
> ...     print "hello"
> ... 
> >>> foo() 
> hello
> 
> # So far, so good.  I've defined a function and called it.
> # Nothing mysterious going on yet.
> 
> >>> z = foo
> >>> z()
> hello
> 
> # This is the gist of what I was trying to demonstate, that
> # names can be bound to anything, and the value of something
> # can be a function just as easily as it can be an integer.
> 
> >>> foo.__name__
> 'foo'
> 
> # Still no problem, a function knows it's name.
> 
> >>> z.__name__
> 'foo'
> 
> # Huh???
> ----------------------------------
> 
> I know why z.__name__ printed 'foo', but I'm not quite sure I know how
> to explain it (at least not without delving into horrible stuff like
> lambdas which are sure to just confuse my audience).

Oh, you were *so* close.  You said

 # This is the gist of what I was trying to demonstate, that
 # names can be bound to anything, and the value of something
 # can be a function just as easily as it can be an integer.

Now the only question is if 'foo' and 'z' refer to the *same*
object.  And this is indeed the case as 'z=foo' binds the *same*
object that foo references to the name  'z'.  If both
point to the same object then it is understandable that

    z.__name__ 

returns 'foo' because the function object was created under
that name and the 'z=foo' binding didn't change the object. 

> So, what exactly does "def foo" do?  It seems that it does two things.
> First, it defines a function, and gives that function's __name__
> attribute the value "foo".  At the same time, it also defines a name
> "foo" in the current namespace, and binds it to the function that was
> just defined.  Is that a good (i.e. correct) way to explain it?  Is
> there a better way that might make more sense to a non computer
> scientist?

Again you are extremely close.  In proper terms you  might say
that 'def foo(): ...' 

    a) creates a function object (with attributes such as the name 'foo' 
       and the body code)

    b) binds the new function object to 'foo' in the local namespace

Actually you can use the dis module to see the underlying "bytecode":

>> def g():
      def f(): print "hallo"

>>> dis.dis(g)
          0 SET_LINENO               1   # <-- forget those SET_LINENO's 
          3 SET_LINENO               2   # they are stupid line numbers
          6 LOAD_CONST               1 (<code object f at 0x8274340, ...
          9 MAKE_FUNCTION            0
         12 STORE_FAST               0 (f)
         15 LOAD_CONST               0 (None)
         18 RETURN_VALUE
>>>

which makes the above sequence pretty obvious. 

> Some time later, she came back and wanted to know why
> 
> for x in [1, 2, 3, 4, 5, 6]:
>     print x if x < 3:
> 
> didn't work :-(  See what I was talking about when I said her brain
> had been corrupted by Perl?

There is ugly syntax for stuff like this in Python :-)
It's called list comprehension 

    [x for x in [1,2,3,4,5,6] if x<3]

regards,

    holger





More information about the Python-list mailing list