<阅读并理解本文需要一定GDscript基础>
事关紧急,咱们就直接步入正题:
!!!但虽然紧急,可本文如有错误,欢迎指出!!!
各位请看一下这个代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=2b3f10a4e4014a90813e46b599773971/8803f8f81a4c510fecd14d0c3d59252dd42aa552.jpg?tbpicau=2024-08-06-05_241e1730d91943fe7a4a068a9e88db89)
很简单,不是吗?上面这段代码就是在_ready函数被加载时,调用test函数。
可在Godot3中,我们试着像其它语言那样,引用函数时就会发现:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=4e7f2f09d42397ddd679980c6983b216/a959bbd3fd1f4134bc4d1390601f95cad0c85ea8.jpg?tbpicau=2024-08-06-05_8a85a9c7b4d909ce67f72e66ab5619e5)
这是错误的!!!
因为Godot3 GDscript中没有用于存储函数的类型!
我们可以这样简单地理解,当GDscript编译器处理到函数,会把它们单独处理,加载到当前节点的函数缓冲区
(注:实际上是gdscript_parser,gdscript_analyzer,gdscript_compiler三个模块分步处理GDscript,为便于理解,统称为GDscript编译器;实际上脚本中的函数编译后存储在脚本实例中,因为可以与节点注册的函数一起使用,这里称“节点的函数缓冲区”)
而调用函数时,例如test(),就被编译器视为运行节点函数缓冲区中的名为test的函数!而且,例如这里的test(),其中的test会被编译器认定为标识符,而不是变量数据!
顺便提一下,所以Godot3变量与函数同名是被允许的
![](http://tiebapic.baidu.com/forum/w%3D580/sign=1414e282553853438ccf8729a312b01f/de1fdfbf6c81800a38e698e0f43533fa838b47a7.jpg?tbpicau=2024-08-06-05_fbab68700c11d268b452d775f9ac9ecc)
![](http://tiebapic.baidu.com/forum/w%3D580/sign=0fc19660af1fbe091c5ec31c5b600c30/7981b4efce1b9d1689f03377aedeb48f8c5464bc.jpg?tbpicau=2024-08-06-05_bed0a115a36a7508a51e0d6dab866bad)
所以在Godot3中,GDscript的变量是无法引用函数的.....
但是可以用call函数近似实现函数引用:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=fe8cd833ee64034f0fcdc20e9fc27980/49641af790529822c7792f2d92ca7bcb0b46d459.jpg?tbpicau=2024-08-06-05_fc1758a5b27b21768f2900d76f78118f)
Object.call()函数
像上面这样,我们可以动态给a赋值为某个函数名,然后通过call就可以调用了。
而call的本质就是在节点的函数缓冲区中搜索指定名称的函数,搜索到后调用
可是,相比来说,call的效率很低,因为使用call时,会先在函数缓冲区中搜索函数!!!而且反复调用,会造成反复搜索,就浪费了性能!!!
所以在Godot4中官方在内置类型(基本数据类型)中添加了Callable类!!!
正如它的名字:“能调用”
它解决了Godot GDscript的引用函数方面的问题:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=6721543dc016fdfad86cc6e6848e8cea/1492be6eddc451da4105a3fdebfd5266d11632f8.jpg?tbpicau=2024-08-06-05_101fc26374bd3a20360a4e3448429ad1)
以上a段和b段代码,效果相同。
Callable本质也就是在节点的函数缓冲区中搜寻指定函数:
所以,手动构造一个Callable类型时,
首先传入一个节点,这里我们我们传入self(当前节点自身)
然后传入一个字符串,表示搜索的函数名
这样,Callable就会在当前节点中,搜索名为“test”的函数
是不是感觉Callable的用法和原来call也没多大差别?确实,传参也是相似的:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=dd335518e2efce1bea2bc8c29f53f3e8/dd5c1df41bd5ad6e90187204c4cb39dbb4fd3cc5.jpg?tbpicau=2024-08-06-05_3494150984da3848a97e86a55fb52bfe)
以上a段和b段代码,效果相同。
但是效率上,Callable就快的多了:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=daa9bf39c8cad1c8d0bbfc2f4f3f67c4/8d61dcfc1e178a8253e6d0b6ab03738da877e892.jpg?tbpicau=2024-08-06-05_123c9118e702211dbf59ff4b41768507)
当然,以上都为Callable与Call的对比,Callable最大的优势在于,GDscript编译器可以直接解析注册的函数,并包装为Callable:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=ff81ae0af61c8701d6b6b2ee177d9e6e/3994c639b6003af3eb75cc8e702ac65c1238b6dc.jpg?tbpicau=2024-08-06-05_44a7c627f070e36f7e6e8e6c22acb244)
(有关GDscript编译器直接解析注册的函数的深入内容,详见下文)
注意,这里再强调一下:
你还记得test()的含义吗?不记得的话,到前面回顾一下吧。
看一下,下面这段代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=575ce0d257d162d985ee621421dfa950/989ab244ad345982e7e34b8451f431adcbef8406.jpg?tbpicau=2024-08-06-05_91d345bace06d235d6235b58593ae2f4)
正如我们之前提到的,平时,我们直接调用一个函数,例如test(),test不会被当做变量数据,所以test()就直接调用缓冲区中的test函数,而不是Callable.... Callable通过内置的call函数调用的
Godot4 GDscript与Godot3 GDscript有一点不同:
全局变量不能和函数同名!!!!!!!!!!
![](http://tiebapic.baidu.com/forum/w%3D580/sign=c9d4031ba5dcd100cd9cf829428b47be/bc5ca351f8198618c469469217ed2e738bd4e646.jpg?tbpicau=2024-08-06-05_5b17160a425e9d7f5b66ca68afb37d38)
.....
当然Callable还有很多内置函数,这里就不叙述了,有兴趣的话,可以自己去翻文档
有关Callable类型的内容大致就这么多了,按道理就该结束了,但在结束之前,不妨来看一下这段代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=940f0a03e6cc7cd9fa2d34d109002104/7f8828c79f3df8dce9a09e7f8811728b46102801.jpg?tbpicau=2024-08-06-05_696c5b31eb6e5b84764868a2308cee36)
还记得我提到的Callable的优势吗?
以上代码运行时,GDscript编译器可以直接解析注册的函数,并包装为Callable。
简化来说,当编译器编译 print(test) 时,因为没有发现test这个变量,但编译器发现了有名称为test的函数,所以编译器就会把变量test替换为Callable:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=40df6fe8e9af2eddd4f149e1bd120102/684eda3d70cf3bc7a9ebdc029400baa1cc112a3f.jpg?tbpicau=2024-08-06-05_702e482ace7a689b190680deee707cf0)
(你不必担心中间的性能消耗,以上只是通俗的解释,实际编译器做的更加精妙)
当然,Callable替换的前提是找不到你写的变量,才去在函数中查找,并转为Callable,请看下面的这个例子:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=870e5e3211e736d158138c00ab514ffc/4857aa12c8fcc3cefcfdd9ddd745d688d53f20e1.jpg?tbpicau=2024-08-06-05_9e02251e3bad7395643cc207a72bc6d8)
因为编译器找到了变量test的定义,所以是不会转换的!!!!
但这里有一个问题:
下面的print(text),是在var test=12之前执行的,
按道理,这时候因为变量text没有定义,
所以编译器应该会把print(text)替换为print(Callable(self,"test"))
![](http://tiebapic.baidu.com/forum/w%3D580/sign=db525318e2efce1bea2bc8c29f53f3e8/dd5c1df41bd5ad6e96797404c4cb39dbb7fd3c26.jpg?tbpicau=2024-08-06-05_e1ed7a6be00bb61d2ad2281a37f6191f)
但实际的输出却是:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=b933bcfbf9315c6043956be7bdb3cbe6/db4026fae6cd7b89c79c2a6d4a2442a7d8330e36.jpg?tbpicau=2024-08-06-05_a9df73c01a9d79d47c3c2d693bec7ab7)
print(text)中的text被当做null来处理了!!!!而且没有报错!!!!
这应该是一个BUG,或者是什么特殊语法,本人也不明白为什么这样变更,所以我在github godot项目中提交了这个问题:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=dc27a7dc1fafa40f3cc6ced59b66038c/4c517e224f4a20a4e9f42c29d5529822730ed039.jpg?tbpicau=2024-08-06-05_d3c6edce6424799a5bf9f3e0c47c3f50)
等后续官方工作人员的解释吧......
好的,Callable的内容到这里就结束了,本文按道理就应该结束了,但是,作为小吧主,鸽了这么久,一直声称自己研究Godot源码去了,总要拿出点研究成果。现在,Now,我要分享一个重大的发现,所以:
正文开始:
最近在研究Godot源码时,发现Godot4的GDscript处理模块中,有一个LambdaNode,也就是用于存储Lambda信息的,我一看,啊?!Godot4 GDscript支持Lambda表达式了?
![](http://tiebapic.baidu.com/forum/w%3D580/sign=3dffa04b08fbb2fb342b581a7f4a2043/3646323fb80e7bec30f6abf7722eb9389b506bbb.jpg?tbpicau=2024-08-06-05_ccd05adeb88cbfb02e108f1ce385ebcc)
并且,还有专门的处理类:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=e64036e61643fbf2c52ca62b807fca1e/c3f87f81800a19d89c2297eb76fa828ba71e4685.jpg?tbpicau=2024-08-06-05_5d4f6930d5b22f4fd8589f57888cd199)
但我在网上根本就没有找到有关Godot Lambda的相关资料!!!
所以我凭着源码,最终了解了Godot的Lambda表达式
首先,明确一点,Godot4 GDscript是支持Lambda表达式的!
所以,就让我们来学习Godot4 GDscript中的Lambda表达式吧:
什么是Lambda表达式?
Lambda表达式也就是匿名函数:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=9441bc19e50e7bec23da03e91f2eb9fa/c256618b4710b91265bc5ee89efdfc039245226a.jpg?tbpicau=2024-08-06-05_8e261accfcf5bc36a674df12508a306b)
在Godot3 GDscript中我们是无法在函数中声明函数
但在Godot4中,我们可以通过匿名函数解决:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=2d507c71e10f4bfb8cd09e5c334e788f/62655c4a20a44623a6a5b68cdd22720e0df3d7bc.jpg?tbpicau=2024-08-06-05_685fd6ee03161565ce097d86597e1a8b)
直观上来看,匿名函数就是普通函数,去掉函数名,
匿名函数会被包装为Callable类型:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=5b4ea14ae1c27d1ea5263bcc2bd4adaf/084f3b381f30e92437e88fdf09086e061c95f753.jpg?tbpicau=2024-08-06-05_5f955be56ae3a8ab0f08d14bb318e4b0)
但实际上匿名函数与普通的函数有很大不同,普通的函数会被加载到当前节点的函数缓冲区,而匿名函数不会,请看这段代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=08b49760af1fbe091c5ec31c5b610c30/7981b4efce1b9d168e853277aedeb48f8c546429.jpg?tbpicau=2024-08-06-05_f92c413bdf2c6a71b5cbe527b7c30964)
get_node是Node类上定义的一个方法,Node.get_node,它不是静态函数,这意味着要调用get_node,你必须基于一个Node类或其它扩展自Node的类,使用XXX.get_node才行!!
在平时的函数中,因为函数最终加载到当前节点的函数缓冲区,
get_node(XXX)会被默认转换为self.get_node(XXX)
所以平时写的get_node,都是基于self(当前节点)调用的,其它节点非静态函数同理...
而匿名函数,不会储存在当前节点的函数缓冲区,所以是无法直接调用get_node等节点的非静态函数的
但我们依旧可以手动传入节点类:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=5e9a2b2667f33a879e6d0012f65d1018/59098158d109b3de17214c7e91bf6c81810a4cd5.jpg?tbpicau=2024-08-06-05_d7f93bd964050ab445599451bbcd368f)
这里我就把当前节点的实例传入,再在它的基础上调用get_node
当然,如果匿名函数只是执行单语句,一行写也可以:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=12074d8451f431adbcd243317b37ac0f/9a8dc2c8a786c917df8efa2f943d70cf3ac757da.jpg?tbpicau=2024-08-06-05_9009ec525ec02b88e7011cab8ebd3eee)
通过匿名函数,我们还可以实现快速的回调函数传递:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=44534c7e91bf6c81f7372ce08c3fb1d7/55e8b70f4bfbfbed73b59e6925f0f736aec31ffb.jpg?tbpicau=2024-08-06-05_e8a4de3bc1365fc025d5f7bb7fe99980)
大致上,匿名函数的基本内容就这些了,毕竟和普通函数也没差多少,
现在,大家一起去探索吧
至于更多的内容,休息休息再发
(待我研究研究Godot中的闭包)
事关紧急,咱们就直接步入正题:
!!!但虽然紧急,可本文如有错误,欢迎指出!!!
各位请看一下这个代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=2b3f10a4e4014a90813e46b599773971/8803f8f81a4c510fecd14d0c3d59252dd42aa552.jpg?tbpicau=2024-08-06-05_241e1730d91943fe7a4a068a9e88db89)
很简单,不是吗?上面这段代码就是在_ready函数被加载时,调用test函数。
可在Godot3中,我们试着像其它语言那样,引用函数时就会发现:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=4e7f2f09d42397ddd679980c6983b216/a959bbd3fd1f4134bc4d1390601f95cad0c85ea8.jpg?tbpicau=2024-08-06-05_8a85a9c7b4d909ce67f72e66ab5619e5)
这是错误的!!!
因为Godot3 GDscript中没有用于存储函数的类型!
我们可以这样简单地理解,当GDscript编译器处理到函数,会把它们单独处理,加载到当前节点的函数缓冲区
(注:实际上是gdscript_parser,gdscript_analyzer,gdscript_compiler三个模块分步处理GDscript,为便于理解,统称为GDscript编译器;实际上脚本中的函数编译后存储在脚本实例中,因为可以与节点注册的函数一起使用,这里称“节点的函数缓冲区”)
而调用函数时,例如test(),就被编译器视为运行节点函数缓冲区中的名为test的函数!而且,例如这里的test(),其中的test会被编译器认定为标识符,而不是变量数据!
顺便提一下,所以Godot3变量与函数同名是被允许的
![](http://tiebapic.baidu.com/forum/w%3D580/sign=1414e282553853438ccf8729a312b01f/de1fdfbf6c81800a38e698e0f43533fa838b47a7.jpg?tbpicau=2024-08-06-05_fbab68700c11d268b452d775f9ac9ecc)
![](http://tiebapic.baidu.com/forum/w%3D580/sign=0fc19660af1fbe091c5ec31c5b600c30/7981b4efce1b9d1689f03377aedeb48f8c5464bc.jpg?tbpicau=2024-08-06-05_bed0a115a36a7508a51e0d6dab866bad)
所以在Godot3中,GDscript的变量是无法引用函数的.....
但是可以用call函数近似实现函数引用:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=fe8cd833ee64034f0fcdc20e9fc27980/49641af790529822c7792f2d92ca7bcb0b46d459.jpg?tbpicau=2024-08-06-05_fc1758a5b27b21768f2900d76f78118f)
Object.call()函数
像上面这样,我们可以动态给a赋值为某个函数名,然后通过call就可以调用了。
而call的本质就是在节点的函数缓冲区中搜索指定名称的函数,搜索到后调用
可是,相比来说,call的效率很低,因为使用call时,会先在函数缓冲区中搜索函数!!!而且反复调用,会造成反复搜索,就浪费了性能!!!
所以在Godot4中官方在内置类型(基本数据类型)中添加了Callable类!!!
正如它的名字:“能调用”
它解决了Godot GDscript的引用函数方面的问题:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=6721543dc016fdfad86cc6e6848e8cea/1492be6eddc451da4105a3fdebfd5266d11632f8.jpg?tbpicau=2024-08-06-05_101fc26374bd3a20360a4e3448429ad1)
以上a段和b段代码,效果相同。
Callable本质也就是在节点的函数缓冲区中搜寻指定函数:
所以,手动构造一个Callable类型时,
首先传入一个节点,这里我们我们传入self(当前节点自身)
然后传入一个字符串,表示搜索的函数名
这样,Callable就会在当前节点中,搜索名为“test”的函数
是不是感觉Callable的用法和原来call也没多大差别?确实,传参也是相似的:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=dd335518e2efce1bea2bc8c29f53f3e8/dd5c1df41bd5ad6e90187204c4cb39dbb4fd3cc5.jpg?tbpicau=2024-08-06-05_3494150984da3848a97e86a55fb52bfe)
以上a段和b段代码,效果相同。
但是效率上,Callable就快的多了:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=daa9bf39c8cad1c8d0bbfc2f4f3f67c4/8d61dcfc1e178a8253e6d0b6ab03738da877e892.jpg?tbpicau=2024-08-06-05_123c9118e702211dbf59ff4b41768507)
当然,以上都为Callable与Call的对比,Callable最大的优势在于,GDscript编译器可以直接解析注册的函数,并包装为Callable:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=ff81ae0af61c8701d6b6b2ee177d9e6e/3994c639b6003af3eb75cc8e702ac65c1238b6dc.jpg?tbpicau=2024-08-06-05_44a7c627f070e36f7e6e8e6c22acb244)
(有关GDscript编译器直接解析注册的函数的深入内容,详见下文)
注意,这里再强调一下:
你还记得test()的含义吗?不记得的话,到前面回顾一下吧。
看一下,下面这段代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=575ce0d257d162d985ee621421dfa950/989ab244ad345982e7e34b8451f431adcbef8406.jpg?tbpicau=2024-08-06-05_91d345bace06d235d6235b58593ae2f4)
正如我们之前提到的,平时,我们直接调用一个函数,例如test(),test不会被当做变量数据,所以test()就直接调用缓冲区中的test函数,而不是Callable.... Callable通过内置的call函数调用的
Godot4 GDscript与Godot3 GDscript有一点不同:
全局变量不能和函数同名!!!!!!!!!!
![](http://tiebapic.baidu.com/forum/w%3D580/sign=c9d4031ba5dcd100cd9cf829428b47be/bc5ca351f8198618c469469217ed2e738bd4e646.jpg?tbpicau=2024-08-06-05_5b17160a425e9d7f5b66ca68afb37d38)
.....
当然Callable还有很多内置函数,这里就不叙述了,有兴趣的话,可以自己去翻文档
有关Callable类型的内容大致就这么多了,按道理就该结束了,但在结束之前,不妨来看一下这段代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=940f0a03e6cc7cd9fa2d34d109002104/7f8828c79f3df8dce9a09e7f8811728b46102801.jpg?tbpicau=2024-08-06-05_696c5b31eb6e5b84764868a2308cee36)
还记得我提到的Callable的优势吗?
以上代码运行时,GDscript编译器可以直接解析注册的函数,并包装为Callable。
简化来说,当编译器编译 print(test) 时,因为没有发现test这个变量,但编译器发现了有名称为test的函数,所以编译器就会把变量test替换为Callable:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=40df6fe8e9af2eddd4f149e1bd120102/684eda3d70cf3bc7a9ebdc029400baa1cc112a3f.jpg?tbpicau=2024-08-06-05_702e482ace7a689b190680deee707cf0)
(你不必担心中间的性能消耗,以上只是通俗的解释,实际编译器做的更加精妙)
当然,Callable替换的前提是找不到你写的变量,才去在函数中查找,并转为Callable,请看下面的这个例子:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=870e5e3211e736d158138c00ab514ffc/4857aa12c8fcc3cefcfdd9ddd745d688d53f20e1.jpg?tbpicau=2024-08-06-05_9e02251e3bad7395643cc207a72bc6d8)
因为编译器找到了变量test的定义,所以是不会转换的!!!!
但这里有一个问题:
下面的print(text),是在var test=12之前执行的,
按道理,这时候因为变量text没有定义,
所以编译器应该会把print(text)替换为print(Callable(self,"test"))
![](http://tiebapic.baidu.com/forum/w%3D580/sign=db525318e2efce1bea2bc8c29f53f3e8/dd5c1df41bd5ad6e96797404c4cb39dbb7fd3c26.jpg?tbpicau=2024-08-06-05_e1ed7a6be00bb61d2ad2281a37f6191f)
但实际的输出却是:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=b933bcfbf9315c6043956be7bdb3cbe6/db4026fae6cd7b89c79c2a6d4a2442a7d8330e36.jpg?tbpicau=2024-08-06-05_a9df73c01a9d79d47c3c2d693bec7ab7)
print(text)中的text被当做null来处理了!!!!而且没有报错!!!!
这应该是一个BUG,或者是什么特殊语法,本人也不明白为什么这样变更,所以我在github godot项目中提交了这个问题:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=dc27a7dc1fafa40f3cc6ced59b66038c/4c517e224f4a20a4e9f42c29d5529822730ed039.jpg?tbpicau=2024-08-06-05_d3c6edce6424799a5bf9f3e0c47c3f50)
等后续官方工作人员的解释吧......
好的,Callable的内容到这里就结束了,本文按道理就应该结束了,但是,作为小吧主,鸽了这么久,一直声称自己研究Godot源码去了,总要拿出点研究成果。现在,Now,我要分享一个重大的发现,所以:
正文开始:
最近在研究Godot源码时,发现Godot4的GDscript处理模块中,有一个LambdaNode,也就是用于存储Lambda信息的,我一看,啊?!Godot4 GDscript支持Lambda表达式了?
![](http://tiebapic.baidu.com/forum/w%3D580/sign=3dffa04b08fbb2fb342b581a7f4a2043/3646323fb80e7bec30f6abf7722eb9389b506bbb.jpg?tbpicau=2024-08-06-05_ccd05adeb88cbfb02e108f1ce385ebcc)
并且,还有专门的处理类:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=e64036e61643fbf2c52ca62b807fca1e/c3f87f81800a19d89c2297eb76fa828ba71e4685.jpg?tbpicau=2024-08-06-05_5d4f6930d5b22f4fd8589f57888cd199)
但我在网上根本就没有找到有关Godot Lambda的相关资料!!!
所以我凭着源码,最终了解了Godot的Lambda表达式
首先,明确一点,Godot4 GDscript是支持Lambda表达式的!
所以,就让我们来学习Godot4 GDscript中的Lambda表达式吧:
什么是Lambda表达式?
Lambda表达式也就是匿名函数:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=9441bc19e50e7bec23da03e91f2eb9fa/c256618b4710b91265bc5ee89efdfc039245226a.jpg?tbpicau=2024-08-06-05_8e261accfcf5bc36a674df12508a306b)
在Godot3 GDscript中我们是无法在函数中声明函数
但在Godot4中,我们可以通过匿名函数解决:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=2d507c71e10f4bfb8cd09e5c334e788f/62655c4a20a44623a6a5b68cdd22720e0df3d7bc.jpg?tbpicau=2024-08-06-05_685fd6ee03161565ce097d86597e1a8b)
直观上来看,匿名函数就是普通函数,去掉函数名,
匿名函数会被包装为Callable类型:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=5b4ea14ae1c27d1ea5263bcc2bd4adaf/084f3b381f30e92437e88fdf09086e061c95f753.jpg?tbpicau=2024-08-06-05_5f955be56ae3a8ab0f08d14bb318e4b0)
但实际上匿名函数与普通的函数有很大不同,普通的函数会被加载到当前节点的函数缓冲区,而匿名函数不会,请看这段代码:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=08b49760af1fbe091c5ec31c5b610c30/7981b4efce1b9d168e853277aedeb48f8c546429.jpg?tbpicau=2024-08-06-05_f92c413bdf2c6a71b5cbe527b7c30964)
get_node是Node类上定义的一个方法,Node.get_node,它不是静态函数,这意味着要调用get_node,你必须基于一个Node类或其它扩展自Node的类,使用XXX.get_node才行!!
在平时的函数中,因为函数最终加载到当前节点的函数缓冲区,
get_node(XXX)会被默认转换为self.get_node(XXX)
所以平时写的get_node,都是基于self(当前节点)调用的,其它节点非静态函数同理...
而匿名函数,不会储存在当前节点的函数缓冲区,所以是无法直接调用get_node等节点的非静态函数的
但我们依旧可以手动传入节点类:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=5e9a2b2667f33a879e6d0012f65d1018/59098158d109b3de17214c7e91bf6c81810a4cd5.jpg?tbpicau=2024-08-06-05_d7f93bd964050ab445599451bbcd368f)
这里我就把当前节点的实例传入,再在它的基础上调用get_node
当然,如果匿名函数只是执行单语句,一行写也可以:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=12074d8451f431adbcd243317b37ac0f/9a8dc2c8a786c917df8efa2f943d70cf3ac757da.jpg?tbpicau=2024-08-06-05_9009ec525ec02b88e7011cab8ebd3eee)
通过匿名函数,我们还可以实现快速的回调函数传递:
![](http://tiebapic.baidu.com/forum/w%3D580/sign=44534c7e91bf6c81f7372ce08c3fb1d7/55e8b70f4bfbfbed73b59e6925f0f736aec31ffb.jpg?tbpicau=2024-08-06-05_e8a4de3bc1365fc025d5f7bb7fe99980)
大致上,匿名函数的基本内容就这些了,毕竟和普通函数也没差多少,
现在,大家一起去探索吧
至于更多的内容,休息休息再发
![](http://tb2.bdstatic.com/tb/editor/images/face/i_f28.png?t=20140803)