Anonymous Functions (and Other Ways to Annoy Your Coworkers) - Joe Kaufeld - 2026
Watch on YouTubeVideo summary
Joe Kaufeld opens his presentation by humorously acknowledging the common frustration developers feel regarding anonymous functions, or lambdas, in Python. He begins with a brief detour into his personal preference for using bitwise invert operators to handle list indexing, arguing that treating the right side of a list as negative one is unintuitive compared to using the tilde operator. After establishing this quirky syntax preference, he transitions to the core topic, defining lambdas as unnamed functions that theoretically perform a single operation. He traces the historical lineage of this concept from Alonzo Church's lambda calculus and Lisp to its adoption in Python, noting that while Guido van Rossum initially wanted to remove these features in favor of list comprehensions, they ultimately remained due to community resistance. Kaufeld clarifies that despite their limitations—such as being restricted to a single expression and lacking variable declarations—lambdas are fundamentally just functions without identifiers.
The speaker then explores practical applications where lambdas are appropriate, such as sorting complex data structures like lists of actors by last name or filtering even numbers from a dataset. He highlights the utility of `map` and `filter` operations but notes that Python's list comprehensions often serve as a more readable alternative for these tasks. Kaufeld shares an advanced use case involving a Pokémon TCG companion app, where he utilized lambdas to dynamically generate data classes for thousands of cards. By leveraging the local scope of lambdas, he could create factory-like functions that pre-filled known data (like set IDs) while leaving other fields open for instantiation, resulting in code that was significantly more readable and maintainable than hardcoding every detail.
In the spirit of his talk's title, Kaufeld proceeds to demonstrate how to "annoy coworkers" by breaking standard rules and creating multi-line lambdas through clever abuse of Python's list evaluation scope and the walrus operator. He shows how one can effectively create decorators or even re-implement timing utilities like `timeit` by wrapping logic inside a lambda that executes immediately upon definition, storing results back into the function name. While he admits these techniques are generally discouraged because they reduce code readability and violate best practices, he encourages the audience to experiment with such "cursed" code for fun, especially if they are the sole maintainers of the project. He concludes by reminding listeners that while lambdas are useful shorthand for simple, localized logic, relying on them excessively can lead to confusion, and he invites attendees to share their own examples of overly complex anonymous functions.
Read the full video transcript
So, uh
this is Joe Corfeld, who is going to
ah
>> radio
>> radio. Uh who's going to uh give us our
last uh I guess Python technical talk of
the conference this year. Uh talking
about something that's very near and
dear to my heart, which is doing the
wrong thing with anonymous functions. Uh
please make him welcome.
>> Thank you very much. Before we get
started, I am going to check in with our
crew. So, welcome to anonymous functions
or how I learned to stop worrying and
love the lambda. I have changed the name
of this talk because when I originally
wrote the uh the outline,
I had a thought for how this was going
to go. And then I actually
like started writing the talk for real.
Um and it ended up that I submitted an
outline for roughly an hour and a half
worth of content for a 25-minute talk.
So, um we have to switch this up a
little bit.
I think it'll be okay though. So,
lambdas, more than you ever wanted to
know about Python lambdas. Um
my name is Joe Corfeld. I am a senior
developer focusing on building really
big applications for lots of people with
really high availability and the former
president of the Grafeas Group. So, if
you
uh were online and are familiar with
Transcribers of Reddit, that was my
project. And I am a maker, breaker, and
professional eater of bread. You can
find me at these places. Uh if you want
to
throw things metaphorically at me, uh
please do it on Mastodon because that's
the easiest place for me to get it. This
slide will be up again at the end.
So, before we really get into this, um I
was talking to Sam before uh this event.
And
I said, "Hey, I have this weird Python
thing that I do a lot and I realize now
that I've written it into all of my
examples. Do you know what this weird
Python thing is?" And he was like, "No."
So, um,
they apologies.
Um, so we're going to take a quick
second and divert from the actual uh,
purpose of our talk and we're going to
talk about bitwise inverts.
Um, so
a bitwise invert is a really fun unary
operation. We're not going to get into
what literally anything I just said
meant, um, but who can tell me what
tilde zero equals?
Minus one, exactly. The general rule for
this is the two's complement. Again,
we're not going to get into that either,
but it is tilde n equals negative n
minus one. This applies for roughly all
numbers and I really like to use this
when we're doing lists and specifically
indexing doing negative indexing because
in my mind the fact that the
well, from your perspective, the left
side of a list is indexed as position
zero and the right side of the list is
indexed as position negative one doesn't
make any sense and I don't like it. So,
instead I use uh, bitwise inverts so
that the left side is zero and the right
side is tilde zero. Inside one is one
and inside one from the other side is
tilde one. I think it makes a lot more
sense. Um,
and again, I accidentally wrote this
into all of my examples. So, now you
know what this piece of syntax is. Thank
you very much for attending my TED Talk.
So,
time for lambdas. Join me on our descent
into hell.
So, uh, we have to make sure that
everybody's is on the same page. So,
we're going to start at the bare bottom.
A
An anonymous function is a function
definition that is not bound to an
identifier.
Which, once you strip away
the crap, just means that we have logic
that doesn't have a name.
That's all it is. We have logic that
works on something in a way that is
theoretically repeatable, but we didn't
give it a name. In Python, this is a
little bit different because we kind of
want to name everything.
Um so, we are going to do that anyway.
Um
But, in general, now we all know. So, a
brief history lesson. In 1936, Alonzo
Church gives us lambda calculus. I am
not going to get into this. We're just
going to look at this slide, and then
we're going to move on because I barely
passed business calc, otherwise known as
calc for weenies.
So, this is what we get. Um
Alonzo Church gave us this particular
setup in that we have four individual
pieces. We have, ignoring the lambda
part for a second, we have X, which is
our variable, the thing that we want to
act upon. Then, we have a period, which
is our separator. It separates the thing
that we want to act upon and the way
that we are going to act upon it. And
then, we have the function body, which
is our operation.
In a normal function, you take these
three things and you wrap them all in a
name.
And you have a function. This is how
functions work at a very basic level. Um
it's just those four pieces. The only
functional difference between a lambda
and a regular function is that you don't
have that encapsulating name. So, we
have lambda, the icon that shows we are
about to launch into this process, the
argument, the separator, and the body.
In 1958, Lisp picked up the lambda as
the first programming language to have
uh this concept and it has very much the
same structure. You have the lambda
keyword, the argument, you have the
separator, the parentheses and the
space, and then the operation that you
are going to perform on the argument.
It is also worth noting um that both in
the original and in Lisp, we have an
implicit return. There is no point where
we have to state that the result of the
operation that we perform will be
returned. It just simply will be
returned. The implicit return is
important because we don't actually have
to specify that we get that information
back. It's just going to come back. This
is in stark
difference
to
well,
JavaScript.
So, in JavaScript, we have an anonymous
function. This is the the main way that
you would create an anonymous function
if you did it the long way. Again,
JavaScript, we're going to be skipping
over a little bit, but we have function,
the way that we define a function, then
we would normally have a name and then
the parentheses A B and then our logic.
Note, we have an explicit return, which
means that for many reasons, this
violates our definition of what a lambda
is and how a lambda works. They did end
up fixing this kind of with arrow
functions. So, now we have the
arguments, we have the separator, the
arrow, and we have the logic and an
implicit return.
So, we're making progress. Go
JavaScript. Yay.
Python's is a little bit similar, but it
looks familiar for all the wrong
reasons. We have a lambda, the actual
keyword lambda that you have to type out
every time. I'm sorry, Amanda.
We have the argument that we work on. We
have the separator, which is the colon,
and then we have the the operation that
we are going to perform on said
argument. In this case, we're going to
multiply the argument by two and then do
an implicit return so that we get it
back.
So,
lambdas
are functions, they
but they've got some rules to them. So,
let's take a look at that real quick.
Lambdas have one operation.
They are one line.
They return one thing.
You cannot declare variables.
And you cannot have shenanigans.
>> Facts. All of that is
>> All of these are wrong and we're going
to disasso we're going to disassemble
most of them. So,
in order to talk about the fun stuff, we
have to talk about ways that you are
supposed to use a lambda.
Okay. So,
reasonable semi reasonable uses of
lambdas. First off, this is the kind of
uses that you're going to see most
often. It's sorting things. When you
sort a piece of data a data structure in
this case, a list, then you have the
ability to specify the a function by
which you are going to sort the data. In
this case, we want to sort the actors
from Scrubs by last name. We can't just
split it down the middle by space
because of John C. McGinley here. So, we
actually have to do a little bit of
working. In this case, we have a lambda
that takes in a name one name at a time.
We split it by spaces. We grab the last
element. That's the squiggly zero per,
remember? That was invert, cool. And
then we lower case it and then we return
it can implicit return. So, that's going
to give us all lower case the last names
of each of these people. That's going to
be put into a separate element or a
separate uh data structure,
sorted and then applied to this data
structure.
This is a totally reasonable use. You
could, in fact, arguably should have
this spread out into a different
function so that you can, you know, unit
test.
Who does that? Anyway, um
another one you may see pretty often is
filtering. In this particular case, we
want to filter by the even numbers out
of a list. So, what we do is we take our
uh our numbers here and we simply check
each one of them to see if it's
divisible by zero. If it's divisible by
zero, we return true, so it gets added
back into our our end result and we have
it. Cool? Cool.
The map function, rarely used in Python
for good reasons.
Um
you can run a any given function over
each individual piece of data in your
iterable. In this case, we just want to
multiply each number in our list by two.
So, we're going to end up with a
thing called X, which is 2 4 6. Cool?
Cool.
Now, something interesting that I
actually ran across um that I haven't
actually ever seen discussed anywhere is
something that I ended up using lambdas
for for a project. Um I wrote a
companion helper app for a mobile game
uh called Pokémon TCG Pocket.
And as part of this, I needed to be able
to track every card that is in the game.
So, I decided to do this with a data
class. It's just class C for card, the
set ID that the card is in, the number
of the card, name of the card, rarity,
et cetera. It's just these four things,
so I don't need to keep track of a lot,
but
uh
there are like 2,100 cards and that is
kind of a lot of data, especially if
you're going to be integrating that,
actually hard coding it into the code
base, which I wanted to do for various
reasons.
So,
I was looking at this and I thought
I know some of this data ahead of time.
But, I don't know all of it. So, every
card set that comes out has between 80
and 220-ish cards that are attached to
it. So, I know that, for example, this
set of cards all have the same ID. I
don't want to type out the same ID every
time.
But, you have to instantiate the data
class with all of its data
at instantiation time.
Otherwise, it gets mad at you or you
have defaults and I didn't want to screw
with that. So, instead I took the harder
route
and we built this. So, lambdas,
remember, can do one thing. They return
one thing, but that one thing can be
anything.
So, what we have here is we have a
lambda that takes in a set ID. This is
the only piece of information that we
know ahead of time. So, because lambdas
have scopes internal,
then
I can return another lambda from my
lambda
that already has the first piece of
information saved and ready to go
because it's in that local scope. So,
what I can do then is I can create
variables, which are essentially
functions,
that have that pre-saved piece of data
in them and then use that to construct
my uh my data classes in a readable way.
When you have, like, 2,000 of these
elements, it's very clear looking at
this what set is it, what card is it,
what piece of information is it. And
when I interact with this in the code
base, this is a data class because the
only thing that's changing is the order
in which I am instantiating it. So, we
have all of the information. It's easier
to read well, a little bit of,
uh, at the beginning, but
actually, after it's assembled, I think
this is much easier to read, and the
folks who have worked on the app with me
have also told me this is easier to
read. So,
you know, fun thing you can do with
that.
Now,
let's take a second to think about our
good options that we've seen here. We
have sort, which, okay, that's you can't
get around that. We have map,
and we have filter,
and we have whatever this is.
So, map and filter
and reduce
and lambdas
are all from Lisp.
And there there is, unfortunately, a
reason for that. It's because prior to
Python 1, there was a guy who really
missed them from Lisp and submitted a a
patch request to add them into Python.
For various reasons, Guido attempted to
get rid of them for Python 3.
In 2005, he wrote an impassioned blog
post about why he thought we should
ditch lambda,
uh, map, filter, and reduce for the
upcoming Python 3 release. Namely, the
fact that, uh,
list comprehensions are easier to read
and, uh, do it just as well,
and they're easier to read, and they're
more Pythonic.
Mhm.
For various reasons, the crowd was
unimpressed.
Uh, so, unfortunately, we were unable to
get rid of most of these, and reduce was
the only one that was,
in Guido's words from earlier today,
demoted.
The rest we're stuck with. Well, might
as well break stuff.
Okay. So, now we have some thoughts. We
know
what we can do with lambdas. We know
what we should do with lambdas. So,
let's see what we shouldn't do with
lambdas.
Ooh.
Okay. So, we know that lambdas are just
functions, right? They're They're
functions that don't have names, but
they can still do everything a function
can.
They hold one thing.
And that one thing
can be anything.
So,
we need to talk about lists for a
second.
Brief segue. This actually works for any
data structure, but we're going to stick
with lists because
they're marginally more readable, and
I'm about to throw some really horrific
code at you. So, we're going to stick
with lists.
So,
again, starting at the bare bottom, just
to make sure we're all on the same page.
Normally, when we have data, we just
stick it in a list, declare it, and
we're done. And congratulations, you
have a list. It has these numbers in it.
But, if we don't know the data that's
going to go into the list when we
assemble the list, we need to pass it a
variable. Then, as we reference the
list, it pulls the values, I'm
simplifying a lot here, and inserts them
into the list, and provides us with our
end result, the thing that we actually
wanted, right? Right. Okay.
The important thing to take out of this
is not
that
this Python 100-level lesson is
possible, but to keep in mind that lists
have their own scope,
which means we can abuse that.
So,
lists not only have scopes,
but they evaluate each cell, moving left
from right,
at the time that you create it.
So, in this particular example, we have
one, two, and one plus a variable. When
we actually call the list, we don't know
what the variable is, so we look inside
the local scope, we pull that variable,
and then we do math on it to get three.
Now, we have everything we need.
In Python 3.8, something very suspicious
happened. And by suspicious, I mean
mostly that the community was very
upset, or at least a subset of the
community was extremely upset, because
we got the walrus operator.
The walrus operator, colon equals,
is
also kind of informally known as the
thing that lets you define variables in
the local scope as part of a larger
logical statement.
Normally, we only use it in places like
this, because frankly, this is the only
good place to use it in something like
this. But, I want to show you something,
and this is a little bit of audience
participation, because
what will this output?
Any guesses?
What?
>> A portal to hell.
>> Well, yes, a portal to hell is a valid
option, but it's not what this is going
to output. What?
Seven, eight. Exactly. So, what's going
to happen is it's going to evaluate this
by assigning seven to T, and then it's
going to move on to the next cell, even
though T has never been described before
in our program. We have created it out
of thin air, and now we can interact
with it, and we can use it in the local
scope of the data structure that we're
interacting with.
Now it gets fun.
Okay, so
Let's talk about decorators.
A decorator is a function that wraps
another function. Uh
decorators, I would say, are maybe a
200-level things, so I'm not going to
get really into it, but what happens if
we just stick an at symbol in front of a
lambda? Cuz it is a function, right?
So
So this is a really basic lambda. What
this does is it takes in a function and
then immediately returns it with no
changes.
But it's still a functional lambda,
which means we can still do functional
lambda things with it. Because what
happens if we wanted to run a function
as soon as it's loaded into the local
scope?
Well, that could look something like
this.
So let's step through this for a second.
We have lambda. Okay, congratulations.
Yay. Is my cursor in the middle? There
we go. Let's move that. Sorry, I didn't
know that was there.
There we go. Okay.
So we have lambda. We have F, that is
our function, that is going to be Well,
it's our argument, but because it's a
decorator, we're going to be passing in
the hello function. Then we have a list.
The first element of the list is going
to be calling the function that we
passed in, which is then going to store
the result in that array as the to
replace the first element.
And then we just give it a normal
reference.
And then we return the last element of
the array, which gives us the normal
reference. This is deliberate. I'm
pointing out that we made this a little
bit complicated specifically because we
need to be able to call this function
again.
If we don't return a a a um
If we don't return a route to the
function originally, we're we're going
to be able to call this again because
it's actually going to overwrite the
hello name in the local scope with the
result of the function running.
Which we can abuse.
So, let's make this a little bit
simpler.
If we do overwrite it, in this case, we
just have lambda F, our function, and
then we immediately call the function
that we passed in. This is simpler,
but what it does is it returns the
output
to the name of the function.
Which effectively means we have
multi-line lambdas.
I do want to shout out to Chris who
pointed out that this was possible, and
I I just took it one step further. I'm
sorry.
Um
so, this actually does allow us to have
multi-line lambdas. We can have a
function of unlimited length.
Stick that lambda on the top, and then
it will immediately run and save the
output to the name of the function as a
regular variable.
You're welcome.
Okay, let's make this more complicated.
Um
Does anybody want to tell me what this
does?
Okay, cool. Uh this is a greenfield
re-implementation of the timeit
decorator.
Because I thought it would be fun.
Um I'm I'm not going to break this down
into its component parts, but what I am
going to explain is that we use lists to
run each individual line of code as a
stand-alone cell in the list. So, we
start by aliasing time so that I can
actually fit this on the slide. We get a
start time as the second cell.
The third cell is we run our function
with all of the arguments that we
originally passed in, and we store the
result of that to R.
The next cell is just R so that we can
reference it more cleanly. Then the last
cell is a print statement that reformats
it into
something that's generally readable. And
then we have tilde one, which means it
is the first one from the right, which
is the result R.
And you can stick this on top of any
function you want and congratulations,
you've re-implemented time it. This was
more fun than it had any right to be.
Okay.
So, unfortunately,
um as I said at the very beginning, I
wrote like an hour and a half worth of
content and I only have 25 minutes,
which is very sad.
So, maybe maybe we'll just have to do
this again.
Okay. So, there were many other things
that I wanted to talk about like um
recursive lambdas
and
uh decorator factories
and other factories.
Um yeah, all kinds of fun stuff. Oh man,
there's so much cool stuff we can do.
So, uh before I go, I am actually going
to leave you with one more horrible
thing um
after the the takeaways. So,
in general, lambdas are great when
they're short and localized.
Make sure that they're readable.
Otherwise, your your co-workers will
will hate you. Not will likely hate you,
they will. It it's just a matter of
time.
You really shouldn't ever use them
otherwise. There are so few
actual
real reasons to use a lambda, honestly.
Just use functions. Uh lambdas are
they're shorthand. Even the the Python
documentation, I was actually going to
submit a PR for this before my talk and
I forgot. Even the Python documentation
says that you should only use a lambda
as a lazy way to define a function.
Like straight up, look it up.
So,
however, doing things the right way is
not necessarily the way that leads to
learning.
So, give yourself permission to write
bad code because
it's so much fun. And honestly, if
you're the only person who's working on
this code, then you are the person who's
going to be mad at you in 6 months when
they have to read this back, so
you'll live. It'll be fine.
Okay. And also, please send me cursed
lambdas. So, I'm giving you the tools
that I have uncovered over the past few
months. Um my friends are really tired
of me sending them code snippets and
being like, "What does this do?" And
them saying, "I have no clue. Who are
you? Stop calling me."
Well, that too.
Okay, so uh one last thing, um
have you ever looked at the core piece
of Python boilerplate that we all have,
if name equals main?
And and thought,
"This is so ugly. I wish I could replace
it with something cooler."
Um I I couldn't actually fit this into
the presentation, but this does handle
edge cases properly for both uh calling
the file that this function is in
and importing it afterwards and still
being able to reference the function uh
in both of those cases afterwards if you
want to call it again. So, you could
just like spam this wherever you want
and it'll just work. Um I don't
recommend it,
but you can.
I wrote this this morning because um
it just kind of popped into my head and
I was like, "I feel like I can do this."
Not that I should do this, but I feel
like I can. Anyway, uh that's what I've
got. Thank you so much. I really
appreciate it.