如何理解Lua中的元表?

How to understand metatable in Lua?

我用过Python,但现在我正在学习Lua,因为Torch。 'metatable'这个词对我来说真的很难理解。例如,metatable 是一种特殊的 table 吗?它如何改变 table 的行为?

元table 只是一个table,用于控制另一个table(或用户数据,或其他Lua 值)的行为。 table 是元table 只是因为它 用作元table。也就是说,作为“元table”并不是table 的基本属性。没有“create_metatable”功能或任何东西。这只是我们用于控制其他 table 的 table 的名称。

对 tables(或用户数据)的某些操作被指定为首先检查 table 的元数据table。如果 table(或用户数据)有元table,并且元table中有特定的key/value对,那么操作将使用那个key/value 对执行该操作而不是正常逻辑。

每个可以被 metatable 覆盖的操作都有一个与之关联的特定键名。因此,如果您尝试对 table 执行加法,系统将在 metatable 中查找 __add 键以访问它。

对中的值通常(尽管不总是)是一个函数。此类功能通常称为“元功能”。它采用的参数及其 return 值的含义由调用它的特定操作定义。一些操作允许值为 table 或其他值。

在 Lua 中,您使用 setmetatable 函数将元数据 table 分配给 table(但不是用户数据)。在 C 中,您使用 lua_setmetatable 函数为 table(或用户数据)分配元table。

Metatables 对于将 C 对象公开为用户数据的 C 代码特别重要。原始用户数据只是一团不透明的比特; Lua 定义了很少的默认情况下可以对它们执行的合法操作。但是通过为它们分配元table,你可以通过元函数赋予用户数据更多的能力。

请注意,除 table 和用户数据之外的 Lua 值可以具有元 table。但是,与 tables 和用户数据不同,每个 Lua 类型的值都共享该类型的 same metatable。所以所有字符串都有相同的 metatable,所有数字都有相同的 metatable,等等

你好

经过一段时间的阅读和理解元table 可能是什么,我想post 一个工作示例。所以每个人都可以看到并感受到它的用处。该示例更改关联的 table 的 # 运算符。因为我意识到 # 只计算正确的未命名键。 # 也忽略 0 和负数。这是工作示例,如何将其替换为计算每个 table 正确的函数...

 # lua
Lua 5.3.5  Copyright (C) 1994-2018 Lua.org, PUC-Rio
> -- Defining a table with 3 key/value pairs
> my_table={[0]=0,[1]=1,['metatable']={}}
> #my_table
1
> -- # is counting wrong it counts only my_table[1]
> -- Now set the empty my_table.metatable to my_table
> setmetatable(my_table,my_table.metatable)
> -- So it can be accessed without getmetatable()
> -- Now replacing # for associated table my_table
> -- in my_table.metatable with the metafuncion __len
> my_table.metatable.__len=function(array) local incr=0 for _ in pairs(array) do incr=incr+1 end return incr end
> -- Let's test # ...
> #my_table
3
> -- Now # is usefull because it counts correct
> -- And my_table.metatable can be set as a metatable for other tables
> -- where # is counting wrong but needed to count the correct way
> #_G
0
> setmetatable(_G,my_table.metatable)
> #_G
45
> #package.loaded
0
> setmetatable(package.loaded,my_table.metatable)
> #package.loaded
12
> -- Like _G or package.loaded for example