微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

什么时候可以在定义之前使用名称?

如何解决什么时候可以在定义之前使用名称?

在 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

它看起来像是被窃听了,因为 NAMENUMBER 在定义之前就被使用了。但实际上,没有NameError,而且这段代码执行得很好。这是如何运作的?你什么时候可以在一个名字被定义之前引用它?

解决方法

Python 知道 four kinds of direct name lookup: builtins / program global、模块全局、函数/闭包体和类体。 NUMBERLexer 在类主体中解析,因此受此类范围的规则约束。

类体在 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 举报,一经查实,本站将立刻删除。