python tutorial - Python Functions - Def, *Arg, **Kwargs - learn python - python programming
Functions def
- The def create a function object and assigns it to a name. Its general format is:
- The statement block becomes the function's body. The def header line specifies a function name and the function bodies often contain a return statement:
- The notable thing here is that the function doesn't define a return datatype.
- Python functions do not specify the datatype of their return value. They don't even specify whether or not they return a value.
- Actually, however, every Python function returns a value if the function ever executes a return statement, and it will return that value. Otherwise, it will return None.
- Everything in Python is a function, all functions return a value even if it is None, and all functions start with def.
- def is an executable code.
- Python functions are written with a new statement, the def. Unlike functions in compiled language def is an executable statement.
- Our function does not exist until Python reaches and runs the def.
- Actually, it's legal to nest def statements inside if statement, while loops, and even other defs.
- In general, def statements are coded in module files and are naturally run to generate functions when a module file is first imported.
- def creates an object and assigns it to a name.
- When Python reaches and runs a def statement, it generates a new function object and assigns it to the function's name.
- As with all assignments, the function name becomes a reference to the function object.
- There's nothing magic about the name of a function. The function object can be assigned to other names, stored in a list, and so son.
- Functions objects may also have arbitrary user-defined attributes attached to them to record data.
- return sends a result object back to the caller.
- When a function is called, the caller stops until the function finishes its work and returns control to the caller.
- Functions that compute a value send it back to the caller with a return statement. The returned value becomes the result of the function call.
def Execute at Runtime
- The def is an executable statement. When it runs, it creates a new function object and assigns it to a name.
- Because it's a statement, a def can appear anywhere a statement can even nested in other statements:
- Output should look like this:
- Because function definition happens at runtime, there's nothing special about the function name. What's important is the object to which it refers:
- Here, the function was assigned to a different name and called through the new name. Functions are just object.
- They are recorded explicitly in memory at program execution time.
- In fact, besides calls, functions allow arbitrary attributes to be attached to record information for later use:
Definitions and Calls
- Here, we typed the definition of a function, times, interactively. It returns the product of its two arguments:
- When Python reaches and runs this def, it creates a new function object that packages the function's code and assigns the object to the name times.
- After the def has run, we can call (run) the function as shown above.
- The times function's body is just a return statement that sends back the result as the value of the call.
- If we want to use it later we could instead assign it to a variable:
- Let's call the function again with different objects passed in:
- That was possible because we never declared the types of variables , argument, or return values in Python.
- We can use times to either multiply numbers or repeat sequences. In other words, what our times function means depends on what we pass into it.
- This is core idea in Python and it is polymorphism.
Intersecting Sequences
- Let's make a function that collects items held in common in two strings:
- The algorithm of the function is:
- for every item in the first argument, if that item is also in the second argument, append the item to the result.
- Now, let's call the intersect function:
- We could have used a single list comprehension expression giving the same result:
- The function intersect is polymorphic. It works on arbitrary types as long as they support the expected object interface:
- We passed in different types of objects: a list and a tuple.
- It's working because we don't have to specify the types of argument ahead of time.
- For intersect, this means that the first argument should support the for loop and the second has to support the in membership test.
- If we pass in objects that do not support these interfaces (e.g., numbers), Python will detect mismatch and raise an exception:
Local Variables
- The variable res inside intersect is what is called a local variable. It is visible only to code inside the function def and that exists only while the function runs.
- All names assigned inside a function are classified as local variables by default.
- They appear when the function is called and disappear when the function exits.
- The return statement at the end of intersect sends back the result object, but the name res goes away.
Argument Matching
Keyword
- Here is the keyword example:
Default
Argument Matching Table
Syntax | Location | Descruption |
---|---|---|
func(value) | Caller | Normal argument: matched by position |
func(name=value) | Caller | Keyword argument: matched by name |
func(*sequence) | Caller | Pass all object in sequence as individual positional arguments |
func(**dict) | Caller | Pass all key/value pairs in dict as individual keyword arguments |
def func(name) | Function | Normal argument: matched any passed value by position or name |
def func(name=value) | Function | Default argument value, if not passed in the call |
def func(*name) | Function | Matches and collects remaining positional arguments in a tuple |
def func(**name) | Function | Matches and collects remaining keyword arguments in a dictionary |
def func(*args, name) | Function | Arguments that must be passed by keyword only in calls |
*args and **kwargs - Collecting and Unpacking Arguments
- Putting *args and/or **kwargs as the last items in our function definition's argument list allows that function to accept an arbitrary number of anonymous and/or keyword arguments.
- Those arguments are called Keyword Arguments. Actually, they are place holders for multiple arguments, and they are useful especially when we need to pass a different number of arguments each time we call the function.
- We may want to use *args when we're not sure how many arguments might be passed to our function, i.e. it allows us to pass an arbitrary number of arguments to our function.
Collecting arguments
- When the f() is called, Python collects all the positional arguments into a new tuple and assigns the variable args to that tuple. Since it is a normal tuple object, it can be indexed:
- We can pass in lists for the args:
- The ** is similar but it only works for keyword arguments. In other words, it collects them into a new dictionary. Actually, ** allows us to convert from keywords to dictionaries:
- The keyword arguments is a special name=value syntax in function calls that specifies passing by name.
- It is often used to provide configuration options.
Unpacking arguments
- We can use the * or ** when we call a function. In other words, it unpacks a collection of arguments, rather than constructing a collection of arguments.
- In the following example, we pass five arguments to a function in a tuple and let Python unpack them into individual arguments:
- In the same way, the ** in a function call unpacks a dictionary of key/value pairs into separate keyword arguments:
- Also, with various combinations:
- Let's test what we've learned so far:
Output:
Arbitrary function
- In the code below, we support any function with any arguments by passing along whatever arguments that were sent in:
- When the code is run, arguments are collected by the A_function.
apply() - deprecated
- The following function accepts any number of positional or keyword arguments:
- If we use the apply():