This article provides a simple introduction to functional programming technology in Python.
In Python, functions are "first-class citizens". That is, functions are on an equal footing with other data types such as int.
Thus, we can assign functions to variables, pass them as arguments to other functions, store them in other data structures (such as dicts), and use them as return values of other functions.
Since other data types (such as string, list, and int) are objects, functions are also objects in Python. Let's look at the example function foo, which prints its own name:
def foo(): print("foo")
Since functions are objects, we can assign function foo to any variable and then call that variable. For example, we can assign a function to the variable bar:
bar = foo bar() #will print "foo" to the console
The statement bar = foo assigns the object referenced by the function foo to the variable bar.
When objects are callable, they are the same as functions, such as object(). This is achieved through the call method.
The example is as follows:
class Greeter: def __init__(self, greeting): self.greeting = greeting def __call__(self, name): return self.greeting + " " + name
Every time we configure an object of the Greeter class, we will create a new object, which is a new name that can be shouted when greeting. As shown below:
morning = Greeter("good morning") #creates the callable object morning("john") # calling the object #prints "good morning john" to the console
The reason why we can call the morning object is that we have used the call method in the class definition. To check if an object is callable, we use the built-in function callable:
callable(morning) #true callable(145) #false. int is not callable.
Functions, like other objects, can be stored inside data structures. For example, we can create a dictionary of int to func. This comes in handy when an int is a shorthand for the step to be performed.
# store in dictionary mapping = { 0 : foo, 1 : bar } x = input() #get integer value from user mapping[x]() #call the func returned by dictionary access
Similarly, functions can be stored in a variety of other data structures.
Functions can also be used as parameters and return values of other functions. Functions that accept functions as input or return functions are called higher-order functions, and they are an important part of functional programming.
Higher-order functions have powerful capabilities. As explained in "Eloquent JavaScript":
"Higher-order functions allow us to abstract actions, not just abstract values."
Let's look at an example. Suppose we want to iterate over a list of items and print them out in sequence. We can easily build an iterate function:
def iterate(list_of_items): for item in list_of_items: print(item)
It looks cool, but it's just a first-level abstraction. What if we want to do something other than print while iterating over the list?
This is the meaning of the existence of higher-order functions. We can create a function iterate_custom, where the list to be iterated over and the function to be applied to each item are the inputs to the iterate_custom function:
def iterate_custom(list_of_items, custom_func): for item in list_of_items: custom_func(item)
This may seem trivial, but it is actually very powerful.
We have raised the level of abstraction to make the code more reusable. Now, not only can we call this function when printing a list, we can also perform arbitrary operations on the list involving sequence iteration.
Functions can also be returned, making things even simpler. Just like we store functions in dict, we can also use functions as control statements to determine the appropriate function. For example:
def add(x, y): return x + y def sub(x, y): return x - y def mult(x, y): return x * y def calculator(opcode): if opcode == 1: return add elif opcode == 2: return sub else: return mult my_calc = calculator(2) #my calc is a subtractor my_calc(5, 4) #returns 5 - 4 = 1 my_calc = calculator(9) #my calc is now a multiplier my_calc(5, 4) #returns 5 x 4 = 20.
Functions can also be inside other functions. This is an "internal function". Intrinsic functions are useful when creating helper functions, small reusable functions that serve as submodules to support the main function.
We can use auxiliary functions when the problem requires a specific function definition (parameter type or order). This non-traditional approach makes problem solving much simpler, for an example see:
http://www-inst.eecs.berkeley.edu/~cs61a/sp12/lectures/lect4-2x3. pdf.
Suppose you want to define a Fibonacci function fib(n), which has only one parameter n, and we must return the nth Fibonacci number.
One possible way to define such a function is to use a helper function to track the first two terms of the Fibonacci sequence (since the Fibonacci number is the sum of the first two numbers).
def fib(n): def fib_helper(fk1, fk, k): if n == k: return fk else: return fib_helper(fk, fk1+fk, k+1) if n <= 1: return n else: return fib_helper(0, 1, 1)
Move the calculation from the function body to the function parameters, which is very powerful. Because it reduces redundant calculations that may occur in recursive methods.
What should we do if we want to write a function before giving the function a name? What if we want to write a short one-line function (such as function foo or mult in the example above)?
我们可以在 Python 中使用 lambda 关键字来定义此类函数。示例如下:
mult = lambda x, y: x * y mult(1, 2) #returns 2
该 mult 函数的行为与使用传统 def 关键字定义函数的行为相同。
注意:lambda 函数必须为单行,且不能包含程序员写的返回语句。
事实上,它们通常具备隐式的返回语句(在上面的示例中,函数想表达 return x * y,不过我们省略了 lambda 函数中的显式返回语句)。
lambda 函数更加强大和精准,因为我们还可以构建匿名函数(即没有名称的函数):
(lambda x, y: x * y)(9, 10) #returns 90
当我们只需要一次性使用某函数时,这种方法非常方便。例如,当我们想填充字典时:
import collections pre_fill = collections.defaultdict(lambda: (0, 0)) #all dictionary keys and values are set to 0
接下来我们来看 Map、Filter 和 Reduce,以更多地了解 lambda。
map 函数基于指定过程(函数)将输入集转换为另一个集合。这类似于上文提到的 iterate_custom 函数。例如:
def multiply_by_four(x): return x * 4 scores = [3, 6, 8, 3, 5, 7] modified_scores = list(map(multiply_by_four, scores)) #modified scores is now [12, 24, 32, 12, 20, 28]
在 Python 3 中,map 函数返回的 map 对象可被类型转换为 list,以方便使用。现在,我们无需显式地定义 multiply_by_four 函数,而是定义 lambda 表达式:
modified_scores = list(map(lambda x: 4 * x, scores))
当我们想对集合内的所有值执行某项操作时,map 函数很有用。
就像名称所显示的那样,filter 函数可以帮助筛除不想要的项。例如,我们想要去除 scores 中的奇数,那么我们可以使用 filter:
even_scores = list(filter(lambda x: True if (x % 2 == 0) else False, scores)) #even_scores = [6, 8]
由于提供给 filter 的函数是逐个决定是否接受每一个项的,因此该函数必须返回 bool 值,且该函数必须是一元函数(即只使用一个输入参数)。
reduce 函数用于「总结」或「概述」数据集。例如,如果我们想要计算所有分数的总和,就可以使用 reduce:
sum_scores = reduce((lambda x, y: x + y), scores) #sum_scores = 32
这要比写循环语句简单多了。注意:提供给 reduce 的函数需要两个参数:一个表示正在接受检查的项,另一个表示所用运算的累积结果。
The above is the detailed content of Detailed article on Python functional programming techniques. For more information, please follow other related articles on the PHP Chinese website!