首页 > 解决方案 > 要求函数的参数在 Lua 中丢失/消失?

问题描述

虽然我并不真正了解 Lua,但这是一种相当出乎意料和奇怪的行为。

假设我有my_module.lua

local function dump(o) -- SO:9168058
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
       if type(k) ~= 'number' then k = '"'..k..'"' end
       s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end


local mymodule = {}

function mymodule.myfunction(indict)
  print(dump(indict))
end

return mymodule

好的,现在我运行这个:

lua5.3 -e "mm=require('my_module'); mm:myfunction({aa=12})"

这不应该很复杂 - 我“导入”模块,并在其中调用一个函数,其中的参数是一个对象(表/关联数组/字典{aa=12})。然后我只是尝试从函数中打印这个参数。但是,我明白了:

$ lua5.3 -e "mm=require('my_module'); mm:myfunction({aa=12})"
{ ["myfunction"] = function: 0x5619aeddf770,} 

因此,对print(dump(indict))inside的响应,传递给的参数在myfunction哪里,Lua 打印 .... ????!indictmyfunction"myfunction"

我什至无法理解这一点——这怎么可能发生?

以及如何将对象作为参数传递给函数,这样当我从函数内打印参数时,会打印作为参数的对象 - 而不是函数本身??!

顺便说一句,即使我只传递一个数字而不是一个对象,也会发生同样的情况,比如:

lua5.3 -e "mm=require('my_module'); mm:myfunction(42)"

编辑:做了一些调试 - 所以有了这个:

function mymodule.myfunction(indict)
  print(indict)
  print(dump(indict))
end

...我在使用数字参数时得到这个打印输出:

$ lua5.3 -e "mm=require('my_module'); mm:myfunction(42)"
table: 0x55f15a7a07a0
{ ["myfunction"] = function: 0x55f15a7a07e0,} 

...所以它根本看不到这个数字,但函数将自己视为第一个参数。

这提醒了我,在 Python 类中,您必须如何将方法编写为以“self”作为第一个参数的函数,所以我尝试了这个:

function mymodule.myfunction(self, indict)
  print("self", self, "indict", indict)
  print(dump(indict))
end

...打印:

$ lua5.3 -e "mm=require('my_module'); mm:myfunction(42)"
self    table: 0x560510b5a7d0   indict  42
42

...或在传递对象的情况下:

$ lua5.3 -e "mm=require('my_module'); mm:myfunction({aa=12})"
self    table: 0x55d51c9d5800   indict  table: 0x55d51c9d5880
{ ["aa"] = 12,} 

……嗯,这更像是……

谁能解释这是从哪里来的 - 为什么在这种情况下我需要添加一个“自我”论点?

标签: lua

解决方案


在 lua 中,调用a:b(x)将对象的引用a作为第一个 ( self) 参数传递给函数b

由于您的模块定义是:

function mymodule.myfunction(indict)

并且调用语句是mm:myfunction,对象/表mm作为第一个参数传递(这里是indict)。

将函数定义更改为

function mymodule:myfunction(indict)

如果你想保持 call like mm:myfunction,或者调用函数 as mm.myfunction


该行为在有关 OOP 概念的PiL 书中进行了详细讨论。

冒号的作用是在方法定义中添加一个额外的隐藏参数,并在方法调用中添加一个额外的参数。冒号只是一种句法工具,虽然很方便;这里没有什么新东西。


推荐阅读