Python 字典 |
|
settagmethod
),在 Lua 5 中不再存在,但已被元方法取代。
Lua 的 table 类型是一个多用途容器,介于 Python 的列表和字典类型之间。以下列表模拟了 Python 的字典。有关此处实现内容的详细信息,请参阅 Python 映射类型的文档 [1]。有关更多信息,请参阅 Python 列表 和 类和方法。该脚本是为 Lua 版本 4.0 编写的。
这段代码是尝试使用 Lua 模拟 Python 功能的练习。它在 Lua 中引发了一些问题,这些问题似乎在 Lua 4.1 中已得到解决。关于此实现的评论:-
foo = Dict:new { len="vcbvcb" } print(foo:len())冒号运算符访问 foo,而不是 Dict。您将缺失的元素(方法)重定向到 Dict,但如果 foo 中已存在该名称,则将使用该名称。阅读 [2] 以获取可能的(已实现且有效的)解决方案。-- ET
settagmethod(tag(Dict), "gettable", function(t,k) if rawget(Dict,k) then return rawget(Dict,k) else return rawget(t,k) end end )
foo:len()
将返回 1,但 foo.len
将返回一个函数,而不是存储的值“vcbvcb”。顺便说一句,Python 列表 仅能正常工作,因为用户索引(始终为数字)和方法(始终为字符串)之间没有冲突。-- ET
代码
-- Emulation of Python dictionaries -- Nick Trout -- thanks to lhf & ET -- See https://www.pythonlang.cn/doc/current/lib/typesmapping.html -- $Header: /Tools/build/pydict.lua 3 11/09/01 14:20 Nick $ Dict = settag({},newtag()) -- handle access to our dictionary table type function Dict._gettable(t,k) -- print("gt",t,k) -- See if the key we are looking for is a method in Dict. -- Note the user may have used a key which has the same name as -- one of our functions, but methods take precidence . eg. -- foo = Dict:new { len="vcbvcb" } print(foo:len()) local v = rawget(Dict,k) if v then return v else -- In Python, if we dont find a key in a dictionary we raise a Key error. v = rawget(t,k) assert(v,"Key error") return v end end settagmethod(tag(Dict), "gettable", Dict._gettable) -- Create a new dictionary. -- eg. dict = Dict:new() or dict = Dict:new{ a=1,b=2 } function Dict:new(t) if not t then t={} end settag(t,tag(Dict)) return t end -- len(a) the number of items in a function Dict:len() -- Note: Lua returns the number of indexed objects, not mapped objects with getn local cnt=0 for k,v in self do cnt=cnt+1 end return cnt end -- Python: a[k] the item of a with key k (1) -- Lua: dict[k] -- Python: a[k] = v set a[k] to v -- Lua: dict[k] = v -- Python: del a[k] remove a[k] from a (1) -- Lua: dict:del(k) function Dict:del(k) self[k] = nil end -- Python: a.clear() remove all items from a -- Lua: dict:clear() function Dict:clear() -- cannot do self = {} as self passed by value -- we cannot change a table inside a for loop -- eg. for k,v in self do self[k]=nil end -- Must collect keys and delete them thus: local t={} for k,v in self do t[k]=1 end for k,v in t do self[k]=nil end end -- Python: a.copy() a (shallow) copy of a -- Lua: dictcopy = dict:copy() function Dict:copy() local d = Dict:new() for k,v in self do d[k] = v end return d end -- Python: k in a 1 if a has a key k, else 0 -- k not in a 0 if a has a key k, else 1 -- a.has_key(k) Equivalent to k in a function Dict:has_key(k) return self[k] -- return value for true, or nil for false end -- Python: a.items() a copy of a's list of (key, value) pairs function Dict:items() local items={} for k,v in self do tinsert(items,{k,v}) end return items end -- Python: a.keys() a copy of a's list of keys function Dict:keys() local keys={} for k,v in self do tinsert(keys,k) end return keys end -- Python: a.update(b) for k in b.keys(): a[k] = b[k] -- Add b to a function Dict:update(b) assert(type(b)=="table") for k,v in b do self[k] = v end end -- Python: a.values() a copy of a's list of values function Dict:values() local vals={} for k,v in self do tinsert(vals,v) end return vals end -- Python: a.get(k[, x]) a[k] if k in a, else x -- Return the value associated with key k or x is key not found function Dict:get(k,x) -- use rawget to avoid invoking "index" tag method if k not found return rawget(self,k) or x end -- Python: a.setdefault(k[, x]) a[k] if k in a, else x (also setting it) -- Set value for k to x if k not found, also return value function Dict:setdefault(k,x) self[k] = rawget(self,k) or x return self[k] end -- Python: a.popitem() remove and return an arbitrary (key, value) pair function Dict:popitem() local k,v = next(self) self[k] = nil return k,v end -- Python len(list) is not the same as getn, must count key-value pairs len = Dict.len -- test using: lua -f pydict.lua -test if arg and arg[1]=="-test" then local prl = function(l) for i=1,getn(l) do write(l[i]) end print() end local prd = function(l) for k,v in l do write(k.."="..v..",") end print() end local dict = Dict:new{a=1,b=2,c=3} prd(dict) dict["d"]=4 ; write("d=4: ") ; prd(dict) dict.e=5 ; write("e=5: ") ; prd(dict) print("dict length: "..dict:len()) dict:del(3) ; write("del[3]: ") ; prd(dict) local d2 = dict:copy() ; write("copy: ") ; prd(d2) d2:clear() ; write("clear: ") ; prd(d2) print("length: "..d2:len()) assert( d2:len()==0 ) assert( dict:has_key("a") ) print('dict:has_key("a") : '..dict:has_key("a")) write("items: ") ; print( getn(dict:items()) ) write("keys: ") ; prl( dict:keys() ) dict:update{ f=6,g=7 } ; write("dict:update{ f=6,g=7 } : ") ; prd(dict) write("values: ") ; prl( dict:values() ) write('dict:get("z",26) : ') print(dict:get("z",26)) write('dict:setdefault("y",25) : ') print(dict:setdefault("y",25)) write('dict:popitem() : '..dict:popitem()..", ") ; prd(dict) local foo = Dict:new { len="vcbvcb" } print(foo:len()) -- same name test -- print(foo["wont find this"]) -- test "key error" end