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

2024-09-25 00:23:02 发布

您现在位置:Python中文网/ 问答频道 /正文

在SLY中,有一个编写计算器的示例(从calc.pyhere复制):

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,并且这段代码执行得很好。这是怎么回事?在定义名称之前,何时可以引用名称


Tags: namefromself名称示例number定义value
1条回答
网友
1楼 · 发布于 2024-09-25 00:23:02

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

类主体在namespace provided by the metaclass中求值,它可以实现名称查找的任意语义。具体地说,slyLexer是一个使用a ^{}作为名称空间的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)

LexerMeta还负责adding the ^{} function to the namespace,因此它可以在不导入的情况下使用

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

相关问题 更多 >