上下文无关语法通常具有树状结构,功能程序也具有树状结构。我并不声称以下内容可以解决您的所有问题,但如果您确定不想使用类似SQLite3.
from functools import partial
def select_keys(keys, from_):
    return ({k : fun(v, row) for k, (v, fun) in keys.items()}
            for row in from_)
def select_where(from_, where):
    return (row for row in from_
            if where(row))
def default_keys_transform(keys, transform=lambda v, row: row[v]):
    return {k : (k, transform) for k in keys}
def select(keys=None, from_=None, where=None):
    """
    SELECT v1 AS k1, 2*v2 AS k2 FROM table WHERE v1 = a AND v2 >= b OR v3 = c
    translates to 
    select(dict(k1=(v1, lambda v1, r: r[v1]), k2=(v2, lambda v2, r: 2*r[v2])
        , from_=table
        , where= lambda r : r[v1] = a and r[v2] >= b or r[v3] = c)
    """
    assert from_ is not None
    idfunc = lambda k, t : t
    select_k = idfunc if keys is None  else select_keys
    if isinstance(keys, list):
        keys = default_keys_transform(keys)
    idfunc = lambda t, w : t
    select_w = idfunc if where is None else select_where
    return select_k(keys, select_w(from_, where))
你如何确保你没有给用户执行任意代码的能力。这个框架承认所有可能的功能。好吧,为了安全起见,您可以在其上设置一个包装器,以公开可接受的函数对象的固定列表。
ALLOWED_FUNCS = [ operator.mul, operator.add, ...] # List of allowed funcs
def select_secure(keys=None, from_=None, where=None):
    if keys is not None and isinstance(keys, dict):
       for v, fun keys.values:
           assert fun in ALLOWED_FUNCS
    if where is not None:
       assert_composition_of_allowed_funcs(where, ALLOWED_FUNCS)
    return select(keys=keys, from_=from_, where=where)
怎么写assert_composition_of_allowed_funcs。在 python 中很难做到这一点,但在 lisp 中很容易。让我们假设 where 是一个要以嘴唇形式评估的函数列表,例如格式 iewhere=(operator.add, (operator.getitem, row, v1), 2)或where=(operator.mul, (operator.add, (opreator.getitem, row, v2), 2), 3)。
这样就可以编写一个apply_lisp函数,确保 where 函数仅由 ALLOWED_FUNCS 或诸如 float、int、str 之类的常量组成。
def apply_lisp(where, rowsym, rowval, ALLOWED_FUNCS):
    assert where[0] in ALLOWED_FUNCS
    return apply(where[0],
          [ (apply_lisp(w, rowsym, rowval, ALLOWED_FUNCS)
            if isinstance(w, tuple)
            else rowval if w is rowsym
            else w if isinstance(w, (float, int, str))
            else None ) for w in where[1:] ])
除此之外,您还需要检查确切的类型,因为您不希望您的类型被覆盖。所以不要用isinstance,用type in (float, int, str)。哦,男孩,我们遇到了:
  Greenspun 的第十条编程规则:任何足够复杂的 C 或 Fortran 程序都包含一个临时的、非正式指定的、充满 bug 的慢速实现,它是 Common Lisp 的一半。