Python - 下一个方法不能与生成器一起正常工作
Python - next method not working properly with generator
我在 python 中制作了一个 class 将代码流拆分为令牌并逐个令牌推进以与它们一起工作
import re
class Tokenizer:
def __init__(self, input_file):
self.in_file = input_file
self.tokens = []
self.current_token = None
self.next_token = None
self.line = 1
def split_tokens(self):
''' Create a list with all the tokens of the input file '''
self.tokens = re.findall("\w+|[{}()\[\].;,+\-*/&|<>=~\n]", self.in_file)
def __iter__(self):
for token in self.tokens:
if token != '\n':
yield token
else:
self.line += 1
def advance(self):
self.current_token = self.next_token
self.next_token = next(self.__iter__())
初始化后:
text = 'constructor SquareGame03 new()\n\
{let square=square;\n\
let direction=direction;\n\
return square;\n\
}'
t = Tokenizer(text)
t.split_tokens()
t.advance()
如果我打印令牌似乎有效
print(t.current_token, t.next_token)
None constructor
但是每隔一次调用 advance 方法都会给出这些结果:
t.advance()
print(t.current_token, t.next_token)
constructor constructor
t.advance()
print(t.current_token, t.next_token)
constructor constructor
所以它没有前进,我不明白为什么。
在这种情况下,.__iter__
实现为 生成器函数 (而不是 生成器迭代器 ),其中 returns一个生成器迭代器.
每次调用 Tokenizer.advance
时,都会创建 一个新的 生成器迭代器 并由 .__iter__
返回。相反,迭代器应在初始化阶段由 Tokenizer
对象存储,以供所有后续使用。
例如:
import re
class Tokenizer:
def __init__(self, input_file):
self.in_file = input_file
self.tokens = []
self.current_token = None
self.next_token = None
self.line = 1
def split_tokens(self):
''' Create a list with all the tokens of the input file '''
self.tokens = re.findall("\w+|[{}()\[\].;,+\-*/&|<>=~\n]", self.in_file)
self.iterator = self.__iter__()
def __iter__(self):
for token in self.tokens:
if token != '\n':
yield token
else:
self.line += 1
def advance(self):
self.current_token = self.next_token
self.next_token = next(self.iterator)
另一个可以解释的最小例子:
def fib():
a = 0
b = 1
while True:
yield b
a, b = b, a + b
# 1, 1, 2, ...
fibs = fib()
next(fibs)
next(fibs)
next(fibs)
# 1, 1, 1, ...
next(fib())
next(fib())
next(fib())
顺便说一句,我看不出混合使用 .__iter__
魔术方法和单独的 .advance
方法的原因。它可能会引起一些混乱。
我在 python 中制作了一个 class 将代码流拆分为令牌并逐个令牌推进以与它们一起工作
import re
class Tokenizer:
def __init__(self, input_file):
self.in_file = input_file
self.tokens = []
self.current_token = None
self.next_token = None
self.line = 1
def split_tokens(self):
''' Create a list with all the tokens of the input file '''
self.tokens = re.findall("\w+|[{}()\[\].;,+\-*/&|<>=~\n]", self.in_file)
def __iter__(self):
for token in self.tokens:
if token != '\n':
yield token
else:
self.line += 1
def advance(self):
self.current_token = self.next_token
self.next_token = next(self.__iter__())
初始化后:
text = 'constructor SquareGame03 new()\n\
{let square=square;\n\
let direction=direction;\n\
return square;\n\
}'
t = Tokenizer(text)
t.split_tokens()
t.advance()
如果我打印令牌似乎有效
print(t.current_token, t.next_token)
None constructor
但是每隔一次调用 advance 方法都会给出这些结果:
t.advance()
print(t.current_token, t.next_token)
constructor constructor
t.advance()
print(t.current_token, t.next_token)
constructor constructor
所以它没有前进,我不明白为什么。
在这种情况下,.__iter__
实现为 生成器函数 (而不是 生成器迭代器 ),其中 returns一个生成器迭代器.
每次调用 Tokenizer.advance
时,都会创建 一个新的 生成器迭代器 并由 .__iter__
返回。相反,迭代器应在初始化阶段由 Tokenizer
对象存储,以供所有后续使用。
例如:
import re
class Tokenizer:
def __init__(self, input_file):
self.in_file = input_file
self.tokens = []
self.current_token = None
self.next_token = None
self.line = 1
def split_tokens(self):
''' Create a list with all the tokens of the input file '''
self.tokens = re.findall("\w+|[{}()\[\].;,+\-*/&|<>=~\n]", self.in_file)
self.iterator = self.__iter__()
def __iter__(self):
for token in self.tokens:
if token != '\n':
yield token
else:
self.line += 1
def advance(self):
self.current_token = self.next_token
self.next_token = next(self.iterator)
另一个可以解释的最小例子:
def fib():
a = 0
b = 1
while True:
yield b
a, b = b, a + b
# 1, 1, 2, ...
fibs = fib()
next(fibs)
next(fibs)
next(fibs)
# 1, 1, 1, ...
next(fib())
next(fib())
next(fib())
顺便说一句,我看不出混合使用 .__iter__
魔术方法和单独的 .advance
方法的原因。它可能会引起一些混乱。