Functions and Lambda Expressions
1. Function
Remember "everything is an object" in Python? Python also treats functions as objects, which can be returned from another function to build higher-order functions, such as:
- parameters are functions
- The return value is a function
function definition
- A function begins with the def keyword, followed by the function name and parentheses ().
- The code executed by the function starts with a colon and is indented.
- return [expression] Ends a function, optionally returning a value to the caller. return without an expression is equivalent to returning None.
def functionname(parameters): "function_docstring" function_suite return [expression]
function call
[example]
def printme(str): print(str) printme("I want to call a user-defined function!") # I want to call a user-defined function! printme("call the same function again") # call the same function again temp = printme('hello') # hello print(temp) # None
function documentation
def MyFirstFunction(name): "During function definition name is a formal parameter" # Because Ta is just a form, indicating that it occupies a parameter position print('passed in{0}is called an argument, because Ta is the specific parameter value!'.format(name)) MyFirstFunction('The program life of the old horse') # The program life of the old horse passed in is called an actual parameter, because Ta is a specific parameter value! print(MyFirstFunction.__doc__) # name is a formal parameter during function definition help(MyFirstFunction) # Help on function MyFirstFunction in module __main__: # MyFirstFunction(name) # name is a formal parameter during function definition
function parameter
Python functions have very flexible and diverse parameter forms, which can implement simple calls and pass in very complex parameters. The parameters from simple to complex are as follows:
- positional argument
- default argument
- variable argument
- keyword argument
- name keyword argument
- parameter combination
1. Positional parameters
def functionname(arg1): "function_docstring" function_suite return [expression]
- arg1 - Positional arguments, which are to be fixed in position when calling the function.
2. Default parameters
def functionname(arg1, arg2=v): "function_docstring" function_suite return [expression]
- arg2 = v - default parameter = default value, when calling the function, if the value of the default parameter is not passed in, it is considered to be the default value.
- The default parameters must be placed after the positional parameters, otherwise the program will report an error.
[example]
def printinfo(name, age=8): print('Name:{0},Age:{1}'.format(name, age)) printinfo('pony') # Name: pony, Age:8 printinfo('pony', 10) # Name: pony, Age:10
- Python allows functions to be called in a different order than they were declared, because the Python interpreter can match parameter values with parameter names.
[example]
def printinfo(name, age): print('Name:{0},Age:{1}'.format(name, age)) printinfo(age=8, name='pony') # Name: pony, Age:8
3. Variable parameters
As the name implies, a variable parameter means that the number of parameters passed in is variable, which can be 0, 1, 2 to any number, and it is a parameter of indefinite length.
def functionname(arg1, arg2=v, *args): "function_docstring" function_suite return [expression]
- *args - Variable arguments, from zero to any, automatically assembled into tuples.
- Variable names with an asterisk (*) hold all unnamed variable arguments.
[example]
def printinfo(arg1, *args): print(arg1) for var in args: print(var) printinfo(10) # 10 printinfo(70, 60, 50) # 70 # 60 # 50
4. Keyword Arguments
def functionname(arg1, arg2=v, *args, **kw): "function_docstring" function_suite return [expression]
- **kw - keyword arguments, can be from zero to any, automatically assembled into a dictionary.
[example]
def printinfo(arg1, *args, **kwargs): print(arg1) print(args) print(kwargs) printinfo(70, 60, 50) # 70 # (60, 50) # {} printinfo(70, 60, 50, a=1, b=2) # 70 # (60, 50) # {'a': 1, 'b': 2}
The similarities and differences between "variadic parameters" and "keyword parameters" are summarized as follows:
- Variadic parameters allow to pass zero to any number of parameters, which are automatically assembled into a tuple when the function is called.
- Keyword arguments allow passing zero to any arguments, which are automatically assembled into a dict inside the function.
5. Named keyword arguments
def functionname(arg1, arg2=v, *args, *, nkw, **kw): "function_docstring" function_suite return [expression]
*, nkw - Named keyword parameters, the keyword parameters that the user wants to enter, are defined in nkw prepend a delimiter *.
- If you want to restrict the names of keyword arguments, you can use "named keyword arguments"
- When using named keyword arguments, take special care that the argument name is not missing.
[example]
def printinfo(arg1, *, nkw, **kwargs): print(arg1) print(nkw) print(kwargs) printinfo(70, nkw=10, a=1, b=2) # 70 # 10 # {'a': 1, 'b': 2} printinfo(70, 10, a=1, b=2) # TypeError: printinfo() takes 1 positional argument but 2 were given
- The parameter name nwk is not written, so 10 is regarded as a "positional parameter", and the original function has only 1 positional function, and now 2 are called, so the program will report an error.
6. Parameter combination
To define a function in Python, you can use positional parameters, default parameters, variable parameters, named keyword parameters, and keyword parameters. Four of these five parameters can be used together, but note that the order of parameter definitions must be:
- Positional parameters, default parameters, variadic parameters, and keyword parameters.
- Positional arguments, default arguments, named keyword arguments, and keyword arguments.
Note the syntax for defining variadic and keyword arguments:
- *args is a variable parameter, and args receives a tuple
- **kw is a keyword parameter, and kw receives a dict
Named keyword arguments are intended to limit the parameter names that the caller can pass in, and to provide default values. Don't forget to write the delimiter * when defining named keyword parameters, otherwise it defines positional parameters.
Warning: While up to 5 arguments can be combined, don't use too many at the same time or the function will be hard to understand.
the return value of the function
[example]
def add(a, b): return a + b print(add(1, 2)) # 3 print(add([1, 2, 3], [4, 5, 6])) # [1, 2, 3, 4, 5, 6]
[example]
def back(): return [1, 'Pony's program life', 3.14] print(back()) # [1, 'Pony's Programmed Life', 3.14]
[example]
def back(): return 1, 'Pony's program life', 3.14 print(back()) # (1, 'Pony's Programmed Life', 3.14)
[example]
def printme(str): print(str) temp = printme('hello') # hello print(temp) # None print(type(temp)) # <class 'NoneType'>
variable scope
- In Python, the variables of the program are not accessible everywhere, and the access rights depend on where the variable is assigned.
- A variable defined inside a function has a local scope, and the variable is called a local variable.
- A variable defined outside a function has a global scope and is called a global variable.
- Local variables can only be accessed within the function in which they are declared, while global variables can be accessed program-wide.
[example]
def discounts(price, rate): final_price = price * rate return final_price old_price = float(input('Please enter original price:')) # 98 rate = float(input('Please enter a discount rate:')) # 0.9 new_price = discounts(old_price, rate) print('The price after discount is:%.2f' % new_price) # 88.20
- The global and nonlocal keywords are used when the inner scope wants to modify a variable in the outer scope.
[example]
num = 1 def fun1(): global num # needs to be declared with the global keyword print(num) # 1 num = 123 print(num) # 123 fun1() print(num) # 123
inline function
[example]
def outer(): print('outer function is called here') def inner(): print('inner function is called here') inner() # This function can only be called inside the outer function outer() # The outer function is called here # The inner function is called here
Closure
- It is an important grammatical structure of functional programming and a special embedded function.
- If a reference is made to an outer non-global scope variable within an inner function, the inner function is considered a closure.
- Through the closure, you can access variables in the outer non-global scope, which is called the closure scope.
[example]
def funX(x): def funY(y): return x * y return funY i = funX(8) print(type(i)) # <class 'function'> print(i(5)) # 40
[Example] The return value of a closure is usually a function.
def make_counter(init): counter = [init] def inc(): counter[0] += 1 def dec(): counter[0] -= 1 def get(): return counter[0] def reset(): counter[0] = init return inc, dec, get, reset inc, dec, get, reset = make_counter(0) inc() inc() inc() print(get()) # 3 dec() print(get()) # 2 reset() print(get()) # 0
[Example: If you want to modify the variables in the closure scope, you need to nonlocal keywords
def outer(): num = 10 def inner(): nonlocal num # nonlocal keyword declaration num = 100 print(num) inner() print(num) outer() # 100 # 100
recursion
- A function is recursive if it internally calls itself.
[Example] n! = 1 x 2 x 3 x ... x n
# use cycle n = 5 for k in range(1, 5): n = n * k print(n) # 120 # use recursion def factorial(n): if n == 1: return 1 return n * factorial(n - 1) print(factorial(5)) # 120
[Example] Fibonacci sequence f(n)=f(n-1)+f(n-2), f(0)=0 f(1)=1
# use cycle i = 0 j = 1 lst = list([i, j]) for k in range(2, 11): k = i + j lst.append(k) i = j j = k print(lst) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] # use recursion def recur_fibo(n): if n <= 1: return n return recur_fibo(n - 1) + recur_fibo(n - 2) lst = list() for k in range(11): lst.append(recur_fibo(k)) print(lst) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
[Example] Set the number of recursive layers. The default recursive layer in Python is 100.
import sys sys.setrecursionlimit(1000)
For a detailed introduction to recursion, see:
2. Lambda expressions
Definition of Anonymous Functions
There are two types of functions in Python:
- Category 1: Regular functions defined with the def keyword
- Type 2: Anonymous functions defined with the lambda keyword
python uses the lambda keyword to create anonymous functions instead of the def keyword, it has no function name, and its syntax is as follows:
lambda argument_list: expression
- lambda - keyword for defining anonymous functions.
- argument_list - function arguments, which can be positional arguments, default arguments, keyword arguments, and have the same argument types as in regular functions.
- :- colon, add a colon between function parameters and expressions.
- expression - is just an expression that takes in function arguments and outputs some value.
Notice:
- There is no return statement in expression because the lambda doesn't need it to return, the result of the expression itself is the return value.
- An anonymous function has its own namespace and cannot access parameters outside its parameter list or in the global namespace.
[example]
def sqr(x): return x ** 2 print(sqr) # <function sqr at 0x000000BABD3A4400> y = [sqr(x) for x in range(10)] print(y) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] lbd_sqr = lambda x: x ** 2 print(lbd_sqr) # <function <lambda> at 0x000000BABB6AC1E0> y = [lbd_sqr(x) for x in range(10)] print(y) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] sumary = lambda arg1, arg2: arg1 + arg2 print(sumary(10, 20)) # 30 func = lambda *args: sum(args) print(func(1, 2, 3, 4, 5)) # 15
Use of anonymous functions
Functional programming means that every block of code is immutable and consists of pure functions. The pure function here means that the functions themselves are independent of each other and do not affect each other. For the same input, there will always be the same output without any side effects.
[Example] Non-functional programming
def f(x): for i in range(0, len(x)): x[i] += 10 return x x = [1, 2, 3] f(x) print(x) # [11, 12, 13]
[Example] Functional programming
def f(x): y = [] for item in x: y.append(item + 10) return y x = [1, 2, 3] f(x) print(x) # [1, 2, 3]
Anonymous functions are often used in high-order functions in functional programming, and there are two main forms:
- Arguments are functions (filter, map)
- The return value is a function (closure)
For example, application in filter and map functions:
- filter(function, iterable) Filter the sequence, filter out the elements that do not meet the conditions, and return an iterator object. If you want to convert it to a list, you can use list() to convert it.
[example]
odd = lambda x: x % 2 == 1 templist = filter(odd, [1, 2, 3, 4, 5, 6, 7, 8, 9]) print(list(templist)) # [1, 3, 5, 7, 9] map(function, *iterables) Map the specified sequence according to the provided function.
[example]
m1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5]) print(list(m1)) # [1, 4, 9, 16, 25] m2 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]) print(list(m2)) # [3, 7, 11, 15, 19]
In addition to these built-in functions of Python, we can also define higher-order functions ourselves.
[example]
def apply_to_list(fun, some_list): return fun(some_list) lst = [1, 2, 3, 4, 5] print(apply_to_list(sum, lst)) # 15 print(apply_to_list(len, lst)) # 5 print(apply_to_list(lambda x: sum(x) / len(x), lst)) # 3.0