input() 和 sys.stdin 有什么区别?

9

我刚开始学习 Python,正在尝试着解决一些在线编程问题。在接受输入时,我经常遇到 sys.stdin。请问 input()sys.stdin 的操作有什么不同呢?


4
文档中有什么不清楚的地方? - BartoszKP
3
sys.stdin和input()的区别是什么? - raj
显然有很多不同之处,因为它们是两个完全不同的东西,你只需看一眼文档就可以看出来,更不用说实际阅读了。所以,与其重复你极其模糊的问题(是的,我们会阅读),请更精确地解释你觉得什么令人困惑。 - BartoszKP
3
这是一个有趣的问题,旨在理解input()sys.stdin之间的全部差异,以及为什么在不同的编程竞赛中(如Codingame、HackerRank、Battle Dev)中都可以用于读取数据的相同目的,但却使用了不同的方法。这肯定没有在文档中提到,我也希望能够得到澄清。 - kotchwane
2个回答

4

通过代码示例进行澄清

我一直在思考同样的问题,所以我想出了以下两个片段,通过模拟sys.stdin来澄清input()的区别:

import sys

def my_input(prompt=''):
  print(prompt, end='') # prompt with no newline
  for line in sys.stdin:
    if '\n' in line: # We want to read only the first line and stop there
      break
  return line.rstrip('\n')

这是更加简洁的版本:

import sys

def my_input(prompt=''):
  print(prompt, end='')
  return sys.stdin.readline().rstrip('\n')

这两个片段与input()函数不同,因为它们无法检测到文件结尾(请参阅下文)。

通过文档进行澄清

官方文档如何描述函数input()

input([prompt])

如果存在提示参数,则将其写入标准输出而不带有尾随换行符。然后,该函数从输入中读取一行,将其转换为字符串(去除尾随换行符)并返回。当读取到EOF时,将引发EOFError异常。

这里是关于 sys.stdin 的描述:

sys.stdin

解释器用于标准输入的文件对象。
stdin 用于所有交互式输入(包括对 input() 的调用);
这些流(sys.stdin、sys.stdout 和 sys.stderr)都是像 open() 函数返回的常规文本文件。[...]

因此,虽然input()是一个函数,但sys.stdin是一个对象(文件对象)。 因此,它具有许多属性,您可以在解释器中探索这些属性,方法是:

> dir(sys.stdin)

['_CHUNK_SIZE',
 '__class__',
 '__del__',
 '__delattr__',
 '__dict__',
 '__dir__',

  ...

 'truncate',
 'writable',
 'write',
 'write_through',
 'writelines']

你可以单独显示其中的某一个,例如:

> sys.stdin.mode
r

这个类还有一些方法,比如readline(),它可以“从文件中读取一行;字符串末尾会留下一个换行符(\n),如果文件最后一行没有换行符,则不会省略。这使得返回值变得明确;如果f.readline()返回一个空字符串,那么已经到达了文件的结尾,而一个空行则用'\n'表示,它是一个只包含一个换行符的字符串。”(1)

完整实现

最后这个方法允许我们完全模拟input()函数,包括它的EOF Exception错误:

def my_input(prompt=''):
  print(prompt, end='')
  line = sys.stdin.readline()
  if line == '': # readline() returns an empty string only if EOF has been reached
    raise EOFError('EOF when reading a line')
  else:
    return line.rstrip('\n')

1
以下是需要翻译的内容:

这里有一些入门资料:

内置函数 input标准输入流中读取一行输入,可选地带有提示信息。但要小心提示信息,因为:

result = input('Do you want to do whatever? ')  ## doesn't work how you'd expect
if result.lower() in ('y', 'ye', 'yes', 'yup', 'ya'):
    do_whatever()
    ...
else:
    do_something_else()
    ...

..将包括提示字符串(因此永远不会等于'y'/'yes'/等)。在我看来,最好先打印提示字符串,然后再调用没有参数的输入函数,就像这样:

print('Do you want to do whatever?')
result = input()  ## notice that there is no prompt string passed to input()
if result.lower() in ('y', 'ye', 'yes', 'yup', 'ya'):
    do_whatever()
    ...
else:
    do_something_else()
    ...

因此,简要概括一下,内置函数input标准输入流(sys.stdin)读取输入,而内置函数print将输出打印到标准输出流(sys.stdout)。还有第三个,标准错误流(sys.stderr),未处理的异常会被打印到其中。

通常情况下,您不必过于担心它。这只是在构建IDE和框架等工具时需要注意。


6
will include the prompt string as well”的意思是“也会包括提示字符串”,即在使用input函数输入时,不仅会接受用户的输入,同时也会输出提示字符串。例如,如果您运行类似于“x = input('here');print(x)”这样的代码,则除非在提示符中输入了“here”,否则不会将“here”输出到解释器。按照您所写的方式,实际上我应该得到“here”的输出以及我输入的任何内容。 - baxx
1
-1. 这不是对你回答的连续负面评价,而是事实。这个回答是不正确的。提示语永远不会被包含在函数input()返回的内容中。 - kotchwane
如果我使用类似 x = input('here');print(x) 的方式进行测试,除非我在提示符处输入 'here',否则我不会在解释器中得到 'here' 的输出。然而,根据你所写的内容,我应该能够得到 'here' 的输出以及我输入的任何内容...谢谢。 - pippo1980

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接