Aide-mémoire : Lua pour développeurs Python

par Damien Mégy   Lua python

Table des matières

Aide-mémoire de syntaxe Lua lorsqu'on vient de Python : faux amis, petites différences etc

1. Généralités

Variables et types

Python Lua
x = 42 local x = 42
name = "Bob" local name = "Bob"
True, False true, false
None nil

Types et conversions

Python Lua
type(x) type(x)
str(x) tostring(x)
int(s) tonumber(s)
float(s) tonumber(s)
bool(x) pas d'équivalent direct

Opérateurs

Python Lua
a == b a == b
a != b a ~= b
a and b a and b
a or b a or b
not a not a

Conditions

Python Lua
if cond: if cond then
elif cond: elseif cond then
else: else
fin de bloc implicite end

Boucles

Attention la borne de fin est incluse dans Lua, contrairement aux range Python où elle est exclue. Il y a des avantages et des inconvénients.

Python Lua
while cond: while cond do
for i in range(10): for i = 0, 9 do
for i in range(1,11): for i = 1, 10 do
for i in range(10,0,-1): for i = 10, 1, -1 do
break break
continue non natif, utiliser goto (ou pas)

Fonctions

Python Lua
def f(x): local function f(x)
return x return x
lambda x: x**2 function(x) return x^2 end

Valeurs multiples

Python Lua
return a, b return a, b
a, b = func() local a, b = func()

Gestion d'erreurs

Python Lua
try: pcall(function() ... end)
raise Exception() error("message")
except Exception as e: récupération via pcall

Modules

Python Lua
import json local json = require("dkjson")
from x import y local y = require("x").y

(Si le module x retourne une table.)

Classes / objets

Python Lua
self.method() self:method()
obj.method() obj.method() (sans passage implicite de self)

Faux amis importants

Python Lua
[] est faux {} est vrai
"" est faux "" est vrai
0 est faux 0 est vrai
variables locales par défaut variables globales sans local

2. Tables, listes et dictionnaires

Généralités

Python Lua
[] {}
[1,2,3] {1,2,3}
{} {}
{"a": 1} {a = 1} ou {["a"] = 1}
lst[0], lst[1] t[1], t[2]
dict["name"] t["name"] ou t.name
len(lst) #t
",".join(lst) table.concat(t, ",")

Attention : #t devient imprévisible si la table contient des trous (nil).

Ajouter

Python Lua
dict[k] = v t[k] = v
lst.append(x) table.insert(t, x) ou t[#t+1] = x
lst.extend(other) boucle ou Penlight tablex.insertvalues()

Suppression

Python Lua
del d[k] t[k] = nil
lst.pop() table.remove(t)
lst.pop(i) table.remove(t, i)

Parcours

Python Lua
for x in lst: for _, x in ipairs(t) do
for i,x in enumerate(lst): for i, x in ipairs(t) do
for k,v in dict.items(): for k,v in pairs(t) do

Recherche

Python Lua
x in lst boucle manuelle
k in dict t[k] ~= nil

Exemple :

local function contains(t, value)
    for _, v in ipairs(t) do
        if v == value then
            return true
        end
    end
    return false
end

Compréhensions

Python Lua
[x*2 for x in lst] boucle manuelle
{k:v for ...} boucle manuelle

Exemple :

local out = {}

for _, x in ipairs(lst) do
    table.insert(out, x * 2)
end

Copie

Il n'y a pas d'équivalent natif de copy.copy(x), copy.deepcopy(x) ou x.copy(). Il faut faire une boucle manuelle ou bien utiliser une librarie comme Penlight :

local tablex = require("pl.tablex")
local copy = tablex.deepcopy(tbl)

Tri

Python Lua
lst.sort() table.sort(t)
sorted(lst) copier puis table.sort()

Filtrage

Python Lua
filter(fn, lst) boucle manuelle
[x for x in lst if cond] boucle manuelle

Map

Python Lua
map(fn, lst) boucle manuelle
list(map(...)) boucle manuelle

Avec Penlight :

local tablex = require("pl.tablex")
local result = tablex.map(fn, tbl)

3. Chaînes de caractères

Les chaînes sont immutables en Lua, et ne sont pas des tables contenant chaque caractère. Comme pour les tables, le premier caractère est celui ayant un index égal à 1, pas 0.

Généralités

Python Lua
"a" + "b" "a" .. "b"
len(s) #s
s[0] string.sub(s, 1, 1)
s[k-1] string.sub(s, k, k)
s[:3] string.sub(s, 1, 3)
s[3:] string.sub(s, 4)
s[-1] string.sub(s, -1)
s.lower() string.lower(s)
s.upper() string.upper(s)

Recherche

Python Lua
s.find("abc") string.find(s, "abc")
"abc" in s string.find(s, "abc") ~= nil
s.startswith(x) s:sub(1,#x) == x
s.endswith(x) s:sub(-#x) == x

Remplacement

Python Lua
s.replace(a,b) string.gsub(s,a,b)

Découpage

Python Lua
s.split(",") pas natif
",".join(lst) pas natif

Avec Penlight :

local stringx = require("pl.stringx")

stringx.split(s, ",")
table.concat(lst, ",")

Formatage

Python Lua
f"{x}" string.format("%s", x)
f"{n:.2f}" string.format("%.2f", n)

Expressions régulières

Python Lua
re.search() patterns Lua
re.match() patterns Lua
regex complètes bibliothèque LPeg

4. Entrées / sorties et fichiers

Lecture complète

Python Lua
open(path).read() io.open(path):read("*a")

L'ouverture sécurisée with open(path) as f: n'a pas d'équivalent natif, à la place on peut faire :

local f = assert(io.open(path, "r"))
local data = f:read("*a")
f:close()

Lecture ligne par ligne

Python Lua
for line in open(path): for line in io.lines(path) do

Écriture

Python Lua
open(path,"w") io.open(path,"w")
f.write(text) f:write(text)

Append

Python Lua
open(path,"a") io.open(path,"a")

Existence d'un fichier

Python Lua
os.path.exists(path) ouverture test
local f = io.open(path, "r")

if f then
    f:close()
end

Suppression, Renommage

Python Lua
os.remove(path) os.remove(path)
os.rename(a,b) os.rename(a,b)

Répertoire courant

Python Lua
os.getcwd() LuaFileSystem : lfs.currentdir()

Liste des fichiers

Python Lua
os.listdir(path) LuaFileSystem
local lfs = require("lfs")

for file in lfs.dir(path) do
    print(file)
end

JSON

Il faut importer une librairie gérant le json:

local json = require("dkjson")
-- ou : local json = require("cjson")

Ensuite, dans les deux cas :

local f = assert(io.open("data.json", "r"))
local t = json.decode(f:read("*a"))
f:close()

Attention, en cas d'erreur de décodage, cjson lève une exception alors que dkjson retourne une valeur d'erreur, que l'on peut gérer avec local t, pos, err = json.decode(f:read("*a")).

Pour lire un fichier JSONL :

for line in io.lines("data.jsonl") do
    local obj, pos, err = json.decode(line)

    if obj then
        print(obj.name)
    else
        print("Error :", err)
    end
end