在提供默认答案的同时询问用户的可移植方式(python2/python3)是什么



我想问用户一个有默认答案的问题,例如:

How many apples do you want? [default 40]: 50
You have requested 50 apples.

如何以一种在Python 2和3中可用的整洁、健壮的方式对其进行编码?如何使默认值的显示方式看起来像上面显示的那样?

我有以下尝试的开始:

def interrogate_with_default(
    prompt  = None,
    default = None
    ):
    readline.set_startup_hook(lambda: readline.insert_text(default))
    #readline.set_startup_hook(lambda: readline.insert_text(
    #    " [default: {default}]: ".format(
    #        default = default
    #    )
    #))
    try:
        return get_input(prompt)
    finally:
        readline.set_startup_hook()
def get_input(
    prompt = None
    ):
    if sys.version_info >= (3, 0):
        return input(prompt)
    else:
        return raw_input(prompt)

number_of_apples = interrogate_with_default(
    prompt  = "How many apples do you want?",
    default = "40"
)

如果问题的焦点是与python 2和python 3的兼容性,那么答案是:不要以临时的方式来做!有很多事情需要注意。如果你无法避免必须支持多个平台,请选择一个为此目的设计的库,并始终如一地使用它。我相信six是目前的技术状态:

from __future__ import print_function
import six

然后使用six.moves.input()读取用户输入。它在python 2上绑定到raw_input,在python 3上绑定到常规input。因此,基本上,您将编写一个python 3程序,在模块顶部提供兼容性管道。

备选方案:您可以编写from six.moves import input,它在python 2上使input()的行为与raw_input()类似。这允许使用更多的"原生"python 3代码,但如果您使用python 2规范阅读它,则会感到困惑。我认为如果代码在python 3风格中始终是安全的。

对于默认设置部分,请保持它的明确性,以便您可以轻松地理解和调试它。我喜欢提前设置默认值。然后我会简单地阅读一个答案,如果它不是空的(有效的),就使用它

apples = 40
...
response = six.moves.input("How many apples do you want? [%d]: " % apples).strip()
if response:
    apples = int(response)

与建议的input("...") or 40技巧相比,这种设置的优点是,你可以进一步验证,忽略负值、分数值、键盘混搭,以及通常不适合你问的特定问题的任何东西(生活中有比非负整数更多的东西)。

在这种情况下,您可以使用try-except块来轻松丢弃非整数值:

if response:
    try:
        apples = int(response)
    except ValueError:
        pass

您可以使用or为用户不输入任何内容的情况提供默认值(因为结果是一个空字符串,计算结果为false-y):

>>> 'foo' or 'bar'
'foo'
>>> '' or 'bar'
'bar'

要将其集成到您可以实际使用的函数中(!r用于调用__repr__,因此例如字符串包含引号):

try:
    input = raw_input
except NameError:
    pass
def interrogate(prompt, default=None):
    """Ask the user to enter a value (or accept optional default)."""
    if default is None:
        return input('{}: '.format(prompt))
    return input('{} [default {!r}]: '.format(prompt, default)) or default

注意遵守风格指南和"请求原谅比允许更容易"跨Python 2.x和3.x工作的方法。尽管这确实掩盖了2.x中的内置功能(有些人显然认为这是一种糟糕的做法),它是一个你无论如何都不应该真正使用的代码(事实上,pylint称它为一个糟糕的内置代码!),并使编写将在2.x中继续运行的3.x风格的代码变得更容易。另一种选择是在这两种情况下都使用别名,例如:

try:
    get_input = raw_input
except NameError:
    get_input = input

则处处使用CCD_ 13;如果你把2.x和3.x视为同等重要,这可能更合适。

这样可以吗?

my_input = int(input("How many apples do you want? [default 40]: ") or "40")

最新更新