When you invoke a function, how does it know how many arguments to expect? How does it distinguish between local and global (and enclosing) variables? How does it know that you defined the function with args and/or *kwargs? And where does it store such things as docstrings, annotations, and defaults?
The short answer is that Python functions are objects – no different from integers, strings, and dicts. And like all other bjects,
functions have attributes. It turns out that those attributes are the source of functions’ power.
In this talk, we’ll peek into function attributes, gaining an understanding of (and appreciation for) the way in which functions are built. We’ll also see the relationship between attributes, functions, and Python bytecodes. And while we’ll be dissecting many functions, I can assure you that none of them will be harmed in our quest for deeper understanding.