[Tutor] Apply() [function calling depends on end parentheses]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Fri Feb 7 12:30:02 2003


On Thu, 6 Feb 2003, Erik Price wrote:

>
>
> Danny Yoo wrote:
>
> [...]
>
> > The thing that makes functions unique from values, like strings and
> > numbers, is that they can be "called" by using those parentheses at
> > the end.  In technical terms, functions can be "applied" or "called".
> > In some programming languages, the term "apply" is prevalent, but in
> > Python, it looks like "call" is the term that is most frequently used.
> > (Perhaps the 'apply()' builtin should have been renamed as 'call()'...
> > but I'm just digressing.  *grin*)
>
> After reading the link you sent earlier in this thread, I noticed that
> the term "callable" is found all over the Python docs.  So Python is a
> lot different from Java, since I don't think that Java considers its
> "callables" (method names) to be true objects that can be passed around
> and referenced with different names.


Yes.  In fact, it's very easy in Python to make something "callable": all
an object needs is a "__call__" magic method:

###
>>> class LabelMaker:
...     def __init__(self, prefix):
...         self.count = 1
...         self.prefix = prefix
...     def __call__(self):
...         next_label = "%s%d" % (self.prefix, self.count)
...         self.count = self.count = 1
...         return next_label
...
>>> header_maker = LabelMaker("header")
>>> header_maker()
'header1'
>>> header_maker()
'header1'
###


*laugh* Doh... that statement in my __call__() was supposed to increment
the count, but I wrote a typo:

    self.count = self.count = 1

rather than:

    self.count = self.count + 1

but I hope that the idea is coming though, even though the code above has
that bug.



Anyway, the idea of callable things is very general in Python, so that
even class instances can look like functions.  There's a builtin called
'callable()' that tells us if something looks callable or not:

###
>>> callable(header_maker)
1
>>> callable("hello world")
0
>>> callable(callable)
1
###




> > That's what makes something like:
> >
> > ###
> >
> >>>>f = sayHello
> >>>>f()
> >
> > hello
> > ###
> >
> > possible: 'f' is a name that's directed to the same function value.
> > The first statement doesn't do an application: it merely does a
> > variable name assignment, just like any other assignment we've seen.
> > We can still get 'f' to fire off by doing the parentheses
> > "application".
>
> That cool!  I have never done something like that.  It would seem like
> there could be some obscure uses for this (like calling different
> functions from within a loop, as if the function was an object and we
> were using polymorphism) but I wonder how often they are used in
> practice?



Tkinter GUI programming uses the idea of passing function values: if we
pass a function to someone else, that someone can later call our function.
If we make a button, we can tell that button, "If you get pressed, apply
my function for me."


Here's an example that tries to show this:

###
import Tkinter
import webbrowser

def openPythonOrg():
    webbrowser.open("http://python.org/doc/lib")

b = Tkinter.Button(text="Press me to open Library Docs",
                   command=openPythonOrg)
b.pack()
Tkinter.mainloop()
###


Hey, instant bookmarks.  *grin*


It's the key to understanding why we do:

    b = Tkinter.Button(text="Press me to open Library Docs",
                       command=openPythonOrg)

and not:

    b = Tkinter.Button(text="Press me to open Library Docs",
                       command=openPythonOrg())


Understanding functions --- that is, seeing how these "callable" things
can be treated as passable values --- makes the "callback" idea in Tkinter
very approachable.




> > Please feel free to ask more questions about this.  I hope this helps!
>
> I have one last question -- where do you learn about these kinds of
> advanced Python concepts, once you've gotten past the understanding of
> functions and basic data types, etc (other than here)?

Actually, I picked up a lot of stuff from here on the mailing list.
Stick around!  *grin*


I think "The Structure and Interpretation of Computer Programs" heavily
influenced the way I think about programming:

    http://mitpress.mit.edu/sicp/

Although the book is not targeted specifically toward Python programmers,
the ideas in SICP can be applied remarkably well in Python.  But I have to
admit a strong bias here, since the introductory CS courses at many
colleges (including Berkeley) use SICP --- there may be something better
out there that I haven't been exposed to yet.



> And where do you see them actually applied in the Real World?

The most down-to-earth example I can think of (this early in the morning)
is list sort()ing.  Think of what happens when we pass a comparison
function to a list's sort method():

###
>>> def cmp_by_len(a, b):
...     return cmp(len(a), len(b))
...
>>> words = "it was the best of times; it was the worst of times".split()
>>> words.sort()
>>> words
['best', 'it', 'it', 'of', 'of', 'the', 'the', 'times', 'times;', 'was',
 'was', 'worst']
>>> words.sort(cmp_by_len)
>>> words
['it', 'it', 'of', 'of', 'the', 'the', 'was', 'was', 'best', 'times',
 'worst', 'times;']
###



I hope this helps!