本文介绍两种pythonic方式重定义内置input函数,使其按顺序返回预设列表中的值,避免使用全局变量和可变状态,兼顾简洁性、可读性与实用性。
在单元测试、算法调试或在线判题(如LeetCode、Codeforces)场景中,我们常需模拟用户输入——即让 input() 函数不再等待终端输入,而是从一组预设值中依次返回。虽然用全局计数器配合闭包能实现(如问题中所示),但这种方式破坏了纯函数性、引入了可变状态,且不够“Pythonic”。
更优雅、更符合Python惯用法的方案是利用迭代器协议,将预设数据转换为可消耗的迭代器,并将其 __next__ 方法直接赋给 input 名称。以下是两种主流实现:
raw_data = ['8', '2', '1']
input = iter(raw_data).__next__
for _ in range(3):
print(input()) # 输出: 8, 2, 1from itertools import islice input = lambda: next(iter(['8','2','1']), '') # 超限时返回空字符串
raw_data = ['8', '2', '1'] input = raw_data[::-1].pop # 翻转后从末尾弹出 → 实际按原序返回 for _ in range(3): print(input()) # 输出: 8, 2, 1
实际调试中,输入常为多行文本(如题目样例):
# 模拟标准输入流:每行一个输入值 input_data = '''\ 8 2 1''' input = iter(input_data.splitlines()).__next__ print(input()) # '8' print(input()) # '2' print(input()) # '1'
该模式天然支持换行符处理,且 splitlines() 自动剥离 \n,无需手动 strip()。
def make_input_mock(data):
it = iter(data)
return lambda: next(it)
input = make_input_mock(['8','2','1'])综上,iter([...]).__next__ 是最推荐的方式——它简洁、健壮、符合Python设计哲学,真正实现了“用迭代器思维解决输入模拟问题”。