说实话,网络上对函数式编程的说法,重说纷纭,我也查了很多资料,感觉还是迷迷糊糊的,哈哈哈。所以我就不针对函数式编程的概念去深究,因为我觉得目前阶段的我并不能很好的整体剖析函数式编程。所以这里仅仅是针对编程语言对函数式编程的应用的角度去诉说我的个人感受
函数式编程是面向数学的抽象,将计算描述为一种表达式求值,一句话,函数式程序就是一个表达式。命令式编程的变量就是函数式编程中表达式的参数。参数应该是无状态不可变的,只要你传入表达式永远是这个参数,那么得到的结果就应该是永远不变的。就像一个数学公式一样。
函数式编程是一种编程范式,我们常见的编程范式有命令式编程,函数式编程,逻辑式编程,常见的面向对象编程是也是一种命令式编程。
简单的说,命令式编程需要我们写出逻辑计算的每一个步骤和流程,一步一步达成目的。而函数式编程追求的是过程无关性,只需要知道要什么参数,你要什么结果,过程让函数自己去做。相对比命令式编程,平时我们写的SQL就很像函数式编程,我只要select * from table order by id
, 你就能从table表中,找到所有的数据,并根据ID去排序。而不需要你自己去做获取数据和排序的过程。
总之,我目前并不能很好的剖析函数式编程的概念,只能从语言应用上表层的角度去看待我所指导的函数式编程。所以如果后序还需要继续研究,那么可以对下面几个概念有更加深入的理解
@维基百科 -闭包
- 在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数
@百度百科 - 闭包
- 闭包包含自由(未绑定到特定对象)变量,这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)
简而言之,闭包
就是一个函数引用了外部环境的自由变量(这个外部环境是指创建该函数的环境)。这个变量本质是不属于该函数的作用域,但是却可以该函数所引用到,并且在创建该自由变量的外部环境消失了,该函数依然可以引用到(按道理,该变量在创建它的环境消失后,应该也要被内存锁释放)。能够满足上面条件的行为,我们就称之为闭包
很多的语言支持嵌套函数, 有的语言不支持。但是没有关系,只要能够让一个函数读取到外部环境的变量,那么我们都可以称之为支持闭包。在PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java等语言中都能找到对闭包不同程度的支持。
闭包最主要的作用或用途就是:
很多语言都支持闭包,但每种语言所支持的程度都不太一样
global
或nonlocal
关键字去声明闭包环境变量,让不可变的环境变量可以在内部函数中得到改变Java匿名内部类
public class Closure {
public static void main(String[] args) {
//外部自由变量
final Integer num = 10;
//匿名类
new Thread(new Runnable() {
//匿名类中的内部函数调用外部自由变量,构成闭包
@Override
public void run() {
int sum = num * 2;
System.out.println(sum);
}
}).start();
}
}
Java lambda表达式
public class Closure {
public static void main(String[] args) {
//外部自由变量
Integer num = 10;
//lambda表达式调用外部自由变量,构成闭包
new Thread(() -> {
int sum = num * 2;
System.out.println(sum);
}).start();
}
}
Python嵌套函数
# 定义嵌套函数
def closure():
num = 10
def print_sum():
sum = num * 2
print(sum)
return print_sum
func = closure()
func()
python的匿名函数必须由lambda开头, py的匿名函数更应用倾向于叫lambda表达式,而不像是Java, 匿名函数是匿名函数,lambda表达式只是描述匿名函数的其中一种方式。
所以,在Python中,我们所说的lambda表达式其实就是py的匿名函数
lambda params : expression
# 定义了一个两变量相加的匿名函数
# py中,函数也是对象,可以赋值给一个对象
func = lambda x,y: x + y
print(func(1,2))
'''
output:
3
'''
# 单参数
list_num = [1,2,3,4,5,6]
result = map(lambda x: x*2,list_num)
print(list(list_num))
"""
output:
[2, 4, 6, 8, 10, 12]
"""
# 多参数
list_num = [1, 2, 3, 4, 5, 6]
list_num2 = [2, 3, 4, 5, 6, 7]
result = map(lambda x,y: x * y, list_num,list_num2)
print(list(result))
"""
output:
[2, 6, 12, 20, 30, 42]
"""
from functools import reduce
# 求1...10的累加结果
from functools import reduce
list_num = [1, 2, 3,4,5,6,7,8,9,10]
result = reduce(lambda x, y: x + y, list_num)
print(result)
"""
output:
55
"""
# 过滤掉值为0的元素
list_num = [1, 0, 0, 1, 0, 1, 0]
result = filter(lambda x: x != 0, list_num)
print(list(result))
"""
output:
[1,1,1]
"""
什么是装饰器?
菜鸟教程:
装饰器(Decorators)是 Python的一个重要部分。简单地说:他们是修改其他函数的功能的函数。他们有助于让我们的代码更简短,也更Pythonic(Python范儿)
装饰器有什么作用?
维基百科
- Python decorators were inspired in part by Java annotations, and have a similar syntax
装饰器模式 or 代理模式
装饰器的使用
当我们想要实现在两个方法f1,f2执行前,都先打印一下执行时间
普通代码场景
import time
# function 1
def f1():
print('This is a func 1')
# function 2
def f2():
print('This is a func 2')
# print_time function
def print_time(func):
print(time.time())
func()
print_time(f1)
print_time(f2)
"""
output:
1561617754.6278098
This is a func 1
1561617754.6278098
This is a func 2
"""
不完善的装饰器使用场景:
import time
# 装饰器
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
# function 1
def f1():
print('this is func 1')
# function 2
def f2():
print('this is func 2')
# 将具体的对象传入,抽象装饰器
# 得到了具体的装饰者
decorator_f1 = decorator(f1)
decorator_f2 = decorator(f2)
decorator_f1()
decorator_f2()
"""
output:
1561617803.2912695
This is a func 1
1561617803.2912695
This is a func 2
"""
装饰器:
import time
# 装饰器
def decorator(func):
def wrapper():
print(time.time())
func()
return wrapper
# function 1 with decorator
@decorator
def f1():
print('this is func 1')
# function 2 with decorator
@decorator
def f2():
print('this is func 2')
f1()
f2()
"""
output:
1561617803.2912695
This is a func 1
1561617803.2912695
This is a func 2
"""
装饰器设计模式
的思想,即不修改对象的本身代码,而是通过装饰者对象嵌套要被修饰的对象, 也或者可以说体现了动态代理模式
的思想, 实现了AOP的功能AOP
), 当然代码量上是更加的简洁易用如果想要装饰器更加通用,支持多个参数,或是可变关键字参数,那么我们只需要修改装饰器模板为
# 装饰器
def decorator(func):
def wrapper(*args,**kwargs):
print(time.time())
func(*args,**kwargs)
return wrapper