如何解决什么时候可以在定义之前使用名称?
在 SLY 中有一个编写计算器的例子(复制自 calc.py
here):
from sly import Lexer
class CalcLexer(Lexer):
tokens = { NAME,NUMBER }
ignore = ' \t'
literals = { '=','+','-','*','/','(',')' }
# Tokens
NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
@_(r'\d+')
def NUMBER(self,t):
t.value = int(t.value)
return t
@_(r'\n+')
def newline(self,t):
self.lineno += t.value.count('\n')
def error(self,t):
print("Illegal character '%s'" % t.value[0])
self.index += 1
它看起来像是被窃听了,因为 NAME
和 NUMBER
在定义之前就被使用了。但实际上,没有NameError
,而且这段代码执行得很好。这是如何运作的?你什么时候可以在一个名字被定义之前引用它?
解决方法
Python 知道 four kinds of direct name lookup: builtins / program global、模块全局、函数/闭包体和类体。 NUMBER
、Lexer
在类主体中解析,因此受此类范围的规则约束。
类体在 namespace provided by the metaclass 中求值,它可以为名称查找实现任意语义。具体来说,sly LexerMeta
是一个 class LexerMetaDict(dict):
...
def __getitem__(self,key):
if key not in self and key.split('ignore_')[-1].isupper() and key[:1] != '_':
return TokenStr(key,key,self.remap)
else:
return super().__getitem__(key)
类,使用 a LexerMetaDict
作为命名空间;此命名空间为未定义的名称创建新标记。
LexerMeta
class LexerMeta(type):
'''
Metaclass for collecting lexing rules
'''
@classmethod
def __prepare__(meta,name,bases):
d = LexerMetaDict()
def _(pattern,*extra):
...
d['_'] = _
d['before'] = _Before
return d
还负责 adding the _
function to the namespace,因此无需导入即可使用。
SELECT
user,resource,TIMESTAMP_TRUNC(timestamp,HOUR) AS hour,COUNT(request) as hour_count
FROM
`table`
GROUP BY
user,hour
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。