gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 14:21:06 26 4
gpt4 key购买 nike

在 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 、模块全局、函数/闭包体和类体。 NAME , NUMBER在类主体中解决,因此受制于这种范围的规则。
类主体在 namespace provided by the metaclass 中进行评估,它可以实现名称查找的任意语义。具体来说,狡猾的LexerLexerMeta使用 a LexerMetaDict 的类作为命名空间;此命名空间为未定义的名称创建新标记。

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

关于python - 什么时候可以在定义之前使用名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66016983/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com