2

我很难理解 Peter Norvig 的代码中的一点,“更好的 Python Lisp 解释器”,在这里

在eval函数中,针对解析,他正在做测试isanstance(x,Symbol)。类 Symbol 之前定义过,但它没有方法,因为它是用 pass 声明的:

 class Symbol(str): pass

这些行构建了一个 symbol_table。

def Sym(s, symbol_table={}):
    "Find or create unique Symbol entry for str s in symbol table."
    if s not in symbol_table: symbol_table[s] = Symbol(s)
    return symbol_table[s]

_quote, _if, _set, _define, _lambda, _begin, _definemacro, = map(Sym, 
"quote   if   set!  define   lambda   begin   define-macro".split())

_quasiquote, _unquote, _unquotesplicing = map(Sym,
"quasiquote   unquote   unquote-splicing".split())

我不明白为什么Symbol(s)会起作用,因为没有定义 Symbol 类的构造函数。之后,eval方法通过以下方式检查令牌是否是符号:

def eval(x, env=global_env):
     "Evaluate an expression in an environment."
      while True:
          if isa(x, Symbol):       # variable reference
              return env.find(x)[x]
          else: #other stuff

isa(x,Symbol)是一个谜。这里在代码中,应该检查token是否是一个变量引用(即x,与之前定义的x)。在我看来,这里的 Symbol(s) 是字符串的装饰,在用

  _quote, _if, _set, _define, _lambda, _begin, _definemacro, = map(Sym, 
     "quote   if   set!  define   lambda   begin   define-macro".split())

您能否根据您对 P. Norvig 的代码或 Python 经验的了解或阅读进行解释?谢谢

4

2 回答 2

4

像所有其他方法一样,__init__是继承的。Symbol继承str__init__.

更新:进一步注意__init__执行初始化,而不是构造,并且初始化代码(效果略有不同)也可以存在于类定义中。这意味着一个有效的对象__init__甚至不需要被调用就可以存在。

于 2012-07-19T13:04:40.457 回答
2

Symbol 的类定义只是它是str. 换句话说,它是大多数意图和目的的字符串。

>>> class Symbol(str): pass
... 
>>> x=Symbol('abc')
>>> x
'abc'

这是一个新的类,这意味着解释器对它的处理会有所不同:

>>> x == 'abc' # __eq__ is inherited
True
>>> x is 'abc' # different memory location from 'abc'
False
>>> y='abc'
>>> y is 'abc'
True

isa是 的(相当不必要的)重新定义isinstance,它只检查变量是否是 的实例Symbol

>>> isa = isinstance
>>> isa('abc', Symbol)
False
>>> isa(x, Symbol)
True
于 2012-07-19T12:59:40.480 回答