”明月如霜,好风如水,清景无限 “
来总结一下,lambda表达式。
C++中的会看起来更详细。总的来说可以把lambda表达式理解为一种方便的自定义函数。
壹
lambda的语法格式:
- capture mutable ->return-type{statement}
[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。作为编辑器判断lambda表达式的特征,这部分必须存在,不能省略。
1、空。没有使用任何函数对象参数,意思只是是只用{statement}:函数体的变量。
2、=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this).不过是按值传递(即不会改变原变量)。而&则是按引用传递(会改变原变量,可以理解成传递了指针)。
3、var。放某些局部变量,默认为值传递,如需引用传递则前面加上&。
4、this。函数体内可以使用Lambda所在类中的成员变量。
5、混着用,但是注意不要有变量重复。错误举例:[=,a],如果a是个局部变量,则已经被=包含。比较常用正确举例[&,a]和[=,&a,&b]
-
(parameters):参数列表。就是正常的函数输入参数,没有参数时()可以省略,但是不建议省略().
-
mutable mutable或exception声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身),默认值传递为const.
-
->return-type 返回值类型,当返回值为void,可省略(此时编译器可以自动推断出返回值类型)。要有返回值时,强烈建议加上。eg.
-> int{statement}
- {statement} 函数主体,可以是空,但{}不可省略。
贰
再看一下,python中的lambda表达式。
fun_1 = lambda x:lambda y:x + y
fun = fun_1(3)
print('fun_1:',fun_1)
print('fun:',fun)
print('fun_1(3):',fun_1(3))
print( fun(2) )
print( (fun_1(3))(2) )
这样看起来,python里的lambda简单多了,标志是关键字lambda,后面则是 (输入) :(输出)
lambda argument_list: expression
argument_list是参数列表,它的结构与Python中函数(function)的参数列表是一样的。
expression是一个关于参数的表达式。表达式中出现的参数需要在argument_list中有定义,并且表达式只能是单行的。这个单行相对于C++{statement}而言,功能上似乎弱化了很多,决定了lambda函数不可能完成复杂的逻辑,但是这也是python简洁干练的体现。
但是在某些情况(build-in内置函数)就是很方便:
herolist_json = requests.get(url_json).json() # 获取英雄列表json文件
##简单map函数的参数:map(function,list)
hero_name = list(map(lambda x: x['cname'], herolist_json)) # 提取英雄的名字
hero_number = list(map(lambda x: x['ename'],herolist_json)) # 提取英雄的编号
list=[i for i in range(1,10)]
sorted(list, key=lambda x: abs(x-5)) ###列表按照和5的距离排序
对于一些把函数地址作为对象的函数,使用lambda充当参数就特别爽。
叁
这是不得不说,lambda函数的特点是匿名&高效。
下面再举个小例子:
#include <functional>
#include <iostream>
using namespace std;
class Test
{
public:
int num;
public:
Test()
{
num = 100;
}
void lambda_test()
{
int i_a = 3;
int i_b = 5;
auto fun1 = [](int value) { int i_a = 4;
cout << "fun1__:i_a="<< value << "\n" << endl; };//没有捕获任何参数,这里int v相当于函数参数
// auto fun1 = [](int v){ cout << this->num<<i_a<<endl ; }; 报错:封闭函数局部变量不能在 lambda 体中引用,除非其位于捕获列表中
fun1(i_a);//通过函数调用
//=按照副本引用this,还有当前块语句所有的局部变量,不可以赋值,但是可以读取
auto fun2 = [=]() {
int i_a = 10;
int i_b = 20;
this->num = 200;
cout << "fun2__:" << "num=" << this->num << " i_a=" << i_a << " i_b=" << i_b << "\n"<<endl;
};
fun2();
cout << "fun2__后lambda_test内修改后" << "num=" << this->num << " i_a=" << i_a << " i_b=" << i_b << "\n" << endl;
//&按照引用的方式操作局部变量,this,可以赋值,可以读取
auto fun3 = [&]() { this->num =300; i_a = 10; i_b = 20; cout << "fun3__:" << "i_a=" << i_a << " i_b=" << i_b << "\n" << endl; };
fun3();
cout << "fun3__lambda_test内修改后num=" << this->num << " i_a=" << i_a << " i_b=" << i_b << "\n" << endl;
//指定铺货的参数i_a 可读可写,i_b只读,this->num 无法访问
auto fun4 = [&i_a, i_b]() { i_a = 13; cout<< "fun4__:" << "i_a=" << i_a << " i_b=" << i_b << "\n" << endl; };
fun4();
cout << "fun4__lambda_test内修改后num=" << this->num << " i_a=" << i_a << " i_b=" << i_b << "\n" << endl;
}
};
int main()
{
//Test test = Test();
//Test test;
//(test).lambda_test();
Test *test = new Test();
(*test).lambda_test();
//Test test = new Test();
//(test).lambda_test();
int val = 0;
//auto const_val_lambda = [=]() { val = 3; }; //直接用val会报错 ,只能新建val !!!
//const_val_lambda();
//cout << "const_val_lambda():" << val <<"\n" <<endl;
auto const_val_lambda = [=](){ int val = 3; }; //直接用val会报错 ,只能新建val !!!
const_val_lambda();
cout <<"const_val_lambda():val="<< val << "\n" << endl; //
auto mutable_val_lambda = [=]() mutable { val = 3; cout << "mutable_val_lambda()函数内部:val=" << val << "\n" << endl; };
mutable_val_lambda();
cout << "main()调用mutable_val_lambda()后:val=" << val << "\n" << endl; // 0
system("pause");
return 0;
}
看起来还是很清楚的。最起码说清了:=和&的区别。至于this你观察一下num就能总结出来了。至于mutable则是自己看main函数里面的,最大的改变是mutable让[=]能在lambda内直接使用局部变量而不报错。但不改变是值传递的本质。以后看到lambda就不用慌了。
喜欢的话记得点赞&将公众号星标啊。
END
作者:不爱跑马的影迷不是好程序猿
喜欢的话请关注点赞👇 👇👇 👇
壹句: 月寒日暖,来煎人寿