元表的总结

1. 啥是元表,为啥需要元表

        在 Lua table 中我们可以访问对应的 key 来得到 value 值,但是却无法对两个 table 进行操作(比如相加)。因此 Lua 提供了元表(Metatable),允许我们改变 table 的行为,每个行为关联了对应的元方法。

        所以通俗的理解就是:元表就是为“一个方法表(类似函数表)“,里面包含了一些解决方案。当一个table设置元表之后,相当于关联了这个方法表

2. 表相关的元方法

        __index 用于对表的访问,相当于一个获取的属性的get 函数。lua 查找表元素的时候其流程总结如下:

* 1 在表中查找

         >>找到了,返回该元素   

        >>找不到,继续

*2 判断是否有元表

        >>没有元表,返回nil

        >>有元表,继续

* 3 判断是否有__index方法

        >>__index为nil, 返回nil

        >>__index为表,则重复1,2,3 的步骤

        >>__index为函数,把table和键值当作参数传递给函数,然后返回这个函数的返回值

    __newindex用于对表的更新,相当于设置属性的set 函数。所以给一个table的属性赋值的的流程如下:

*1 查找tabie 中是否有这个字段 >> 有,更新该字段 >>没有,检查是否有元表 ,并且元表是否有__newindex方法>> 没有,则给table 添加该字段,>>有,判断__newindex 的值>>如果__newindex是一个函数,则在给table不存在的函数赋值的时候,会调用这个函数>>如果__newindex是一个表,则在给table不存在字段赋值的时候,则会直接给__newindex的table赋值。

今天被问个问题,如何让一个表的属性不被修改,就是利用__newindex,设置元素

metatable.__newindex= function(t,key,value)     print(“设置了不能被修改”)end  一时没想起来,故作此记录下,下面是简单的实现:

function read_only_tb( tb_b )
	local tb_a = {}
	local tb_c = {}
	tb_c.__index = tb_b
	tb_c.__newindex = function ( t,k,v )
		print("该表设置了不能被修改")
	end
	setmetatable(tb_a,tb_c)
	return tb_a
end

 测试代码和结果:

---测试
local tb_b = {a= 1,b= 2,c= 3}
local tb_proxy = read_only_tb(tb_b)
print("获取只读属性:",tb_proxy.a)
tb_proxy.a = 12

上面只是比较简单的测试,只读table的实现原理,如果要真正应用,那么可能考虑的情况会更多,比目标table本身就设置了元表, 表中的字段可能又是一个table等等。所以整理的比较完整的设置配置的table 为只读的实现:

function read_only(inputTable)
    local travelled_tables = {}
    local function __read_only(tbl)
        if not travelled_tables[tbl] then
            local tbl_mt = getmetatable(tbl)
            if not tbl_mt then
                tbl_mt = {}
                setmetatable(tbl, tbl_mt)
            end

            local proxy = tbl_mt.__read_only_proxy
            if not proxy then
                proxy = {}
                tbl_mt.__read_only_proxy = proxy
                local proxy_mt = {
                    __index = tbl,
                    __newindex = function (t, k, v) error("error write to a read-only table with key = " .. tostring(k)) end,
                    __pairs = function (t) return pairs(tbl) end,
                    -- __ipairs = function (t) return ipairs(tbl) end,   5.3版本不需要此方法
                    __len = function (t) return #tbl end,
                    __read_only_proxy = proxy
                }
                setmetatable(proxy, proxy_mt)
            end
            travelled_tables[tbl] = proxy
            for k, v in pairs(tbl) do
                if type(v) == "table" then
                    tbl[k] = __read_only(v)
                end
            end
        end
        return travelled_tables[tbl]
    end
    return __read_only(inputTable)
end

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django通过ORM功能可以方便地将代码中的类映射为数据库表。首先,在Django的settings.py文件中配置数据库连接信息,包括数据库引擎、数据库名、用户名、密码、主机和端口等。接着,在应用的models.py文件中定义模型类,并且使用不同的字段类型来定义表的列,以及其他的元数据,比如表名。最后,在子应用的admin.py文件中,可以通过注册模型类来自动生成管理页面,这样可以方便地在后台进行增删改查的操作。 举个例子,如果我们有一个名为User的模型类,我们可以在models.py文件中创建一个User类,并定义它的字段。比如,我们可以定义一个名为name的CharField字段,用来表示用户的姓名,还可以定义一个名为level的IntegerField字段,表示用户的级别。同时,我们还可以定义一个名为createTime的DateTimeField字段,用来表示用户的创建时间。为了将这个模型类映射为数据库表,我们需要在Meta类中指定db_table属性,将其设置为表名。 当我们运行Django的数据库迁移命令时,Django会根据模型类的定义自动创建对应的数据库表。具体来说,Django会生成一条创建表的SQL语句,并执行这个SQL语句来创建表。 总结来说,通过配置数据库连接信息、定义模型类和字段、注册模型类生成管理页面,Django可以帮助我们快速创建数据库表。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值