- 5.1 Function Definitions
- 5.2 Default Arguments
- 5.3 Variadic Arguments
- 5.4 Keyword Arguments
- 5.5 Variadic Keyword Arguments
- 5.6 Functions Accepting All Inputs
- 5.7 Positional-Only Arguments
- 5.8 Names, Documentation Strings, and Type Hints
- 5.9 Function Application and Parameter Passing
- 5.10 Return Values
- 5.11 Error Handling
- 5.12 Scoping Rules
- 5.13 Recursion
- 5.14 The lambda Expression
- 5.15 Higher-Order Functions
- 5.16 Argument Passing in Callback Functions
- 5.17 Returning Results from Callbacks
- 5.18 Decorators
- 5.19 Map, Filter, and Reduce
- 5.20 Function Introspection, Attributes, and Signatures
- 5.21 Environment Inspection
- 5.22 Dynamic Code Execution and Creation
- 5.23 Asynchronous Functions and await
- 5.24 Final Words: Thoughts on Functions and Composition
5.8 Names, Documentation Strings, and Type Hints
The standard naming convention for functions is to use lowercase letters with an underscore ( _ ) used as a word separator—for example, read_data() and not readData(). If a function is not meant to be used directly because it’s a helper or some kind of internal implementation detail, its name usually has a single underscore prepended to it—for example, _helper(). These are only conventions, however. You are free to name a function whatever you want as long as the name is a valid identifier.
The name of a function can be obtained via the __name__ attribute. This is sometimes useful for debugging.
>>> def square(x): ... return x * x ... >>> square.__name__ 'square' >>>
It is common for the first statement of a function to be a documentation string describing its usage. For example:
def factorial(n): ''' Computes n factorial. For example: >>> factorial(6) 120 >>> ''' if n <= 1: return 1 else: return n*factorial(n-1)
The documentation string is stored in the __doc__ attribute of the function. It’s often accessed by IDEs to provide interactive help.
Functions can also be annotated with type hints. For example:
def factorial(n: int) -> int: if n <= 1: return 1 else: return n * factorial(n - 1)
The type hints don’t change anything about how the function evaluates. That is, the presence of hints provides no performance benefits or extra runtime error checking. The hints are merely stored in the __annotations__ attribute of the function which is a dictionary mapping argument names to the supplied hints. Third-party tools such as IDEs and code checkers might use the hints for various purposes.
Sometimes you will see type hints attached to local variables within a function. For example:
def factorial(n:int) -> int: result: int = 1 # Type hinted local variable while n > 1: result *= n n -= 1 return result
Such hints are completely ignored by the interpreter. They’re not checked, stored, or even evaluated. Again, the purpose of the hints is to help third-party code-checking tools. Adding type hints to functions is not advised unless you are actively using code-checking tools that make use of them. It is easy to specify type hints incorrectly—and, unless you’re using a tool that checks them, errors will go undiscovered until someone else decides to run a type-checking tool on your code.