在Python中读取一系列输入/输出

0 投票
3 回答
808 浏览
提问于 2025-04-15 23:01

为了我的应用程序,我需要打印出一系列的输出,然后接受用户的输入。有什么好的方法可以做到这一点呢?

比如说:

print '1'
x = raw_input()

print '2'
y = raw_input()

像这样,但我需要重复至少10次。我唯一担心的是这样做会让代码变得不太容易阅读。

我该怎么做呢?我是不是应该像这样创建一个函数:

def printOut(string):
   print string

或者有没有更好的方法呢?

3 个回答

0

如果你在读取多个字段的数据,可能会想要这样做:

field_defs = [
    ('name', 'Name'),
    ('dob' , 'Date of Birth'),
    ('sex' , 'Gender'),
    #...
    ]

# Figure out the widest description.    
maxlen = max(len(descr) for (name, descr) in field_defs)

fields = {}
for (name, descr) in field_defs:
    # Pad to the widest description.
    print '%-*s:' % (maxlen, descr),
    fields[name] = raw_input()

# You should access the fields directly from the fields variable.
# But if you really want to access the fields as local variables...
locals().update(fields)

print name, dob, sex
0

“代码可读性差了10倍...”

其实并不是这样。你需要提供更复杂的例子。

20行代码根本不算什么。为了避免写这20行代码,你可能会写出超过20行的代码。

另外,你也应该看看raw_input的说明。可以在这里查看:http://docs.python.org/library/functions.html#raw_input

它会显示一个提示信息。你写的那四行代码实际上是:

x = raw_input( '1' )
y = raw_input( '2' )

这个代码已经不能再简化了。

2

首先要说明的是,raw_input()可以接受一个可选的参数,也就是提示信息。

关于更广泛的问题,一个简单的方法是创建一个类,这个类定义了你表单的元素,并提供输入、验证以及后续处理或输出的功能。

通过这样的类,可以创建实例(也就是对象),并进行收集、存储等操作。

这样的做法其实并不复杂,像下面这样就可以了:

#!/usr/bin/python
# I use /usr/bin/env python; but making SO's syntax highlighter happy.

class generic_form:
    def __init__(self, element_list):
        self.form_elements = element_list
        self.contents= dict()

    def fill_it_in(self):
        for prompt in self.form_elements:
            self.contents[prompt] = raw_input(prompt)

    def get(self, item):
        return self.contents[item]

    def print_it(self):
        for each in self.form_elements:
            print each, self.contents[each]

if __name__ == '__main__':
    sample_fields = ("Given Name: ",
                     "Surname: ",
                     "Date of Birth: ",
                     "Notes: ")

    example = generic_form(sample_fields)

    print "Fill in my form:"
    example.fill_it_in()

    print
    print "Please review your input:"
    example.print_it()

    # store(:%s, %s: %s" % (example.get('Surname: '), \
    #    example.get('Given Name: '), example.get('Notes: '))

主要的代码只有十几行,定义了一个通用的表单类,具备输入和输出的功能(还有一个简单的get()方法,用于进一步说明)。

这个例子其余部分只是创建了一个实例,并展示了它的使用方式。

因为我的generic_form类是通用的,所以我们需要提供一个字段名称的列表,这些字段需要填写。这个名称在后续访问时会用到(可以参考get()方法的例子)。个人来说,我不会这样做,我会提供一个简短的字段名称和提示,类似于Marcelo的例子。不过,我希望这个例子尽可能简短,以便传达主要观点。

(最后的注释是一个假设的“store()”函数调用,用于将数据存储以备后用。)

这是最简单的方法。然而,你很快会发现,拥有一个更丰富的类,能够对每个字段进行验证,并且有不同的类来格式化和输出这些实例,以及不同的输入类,会更加有用。“电传”输入(就是Python的raw_input()内置函数提供的)是最简单的形式(主要是为了简单和能够通过shell重定向处理文件)。你还可以支持使用GNU的readline(已经作为Python的标准库包含),还有curses支持(同样包含),你甚至可以想象编写一些HTML包装和CGI代码来处理基于网页的输入。

如果我们把“raw_input()”和“print”结合到我们的类中,那么如果我们需要或想要支持其他形式的输入或输出,就会变得更加复杂。

如果我们创建一个只关注要收集数据的类,那么它可以为任何其他输入类提供一个接口,以获取提示列表,并引用“setter”函数(也许还有一个“必填”或“可选”标志)。然后,任何输入类的实例都可以请求任何表单所需的输入列表……展示提示,调用“setter”方法(返回一个布尔值,表示提供的数据是否有效),对“必填”字段的错误输入进行循环处理,提供跳过“可选”字段的选项,等等。

注意,显示提示、接受响应、通过它们的setter方法将这些响应传回数据对象,以及处理无效输入的逻辑,对于许多类型的表单都是相同的。我们只需要一种方式,让表单提供提示列表及其对应的验证函数(并确保所有这些验证函数具有相同的语义——接受相同的参数等等)。

下面是一个将输入行为与数据字段的存储和验证分开的例子:

   #!/usr/bin/env python

    class generic_form:
        def __init__(self, element_list):
            self.hints = list()
            for each in element_list:
                self.hints.append((each, each, self.store))
            self.contents= dict()
        def store(self, key, data):
            '''Called by client instances
            '''
            self.contents[key] = data
            return True

        def get_hints(self):
            return self.hints

        def get(self, item):
            return self.contents[item]


    def form_input(form):
        for each, key, fn in form.get_hints():
            while True:
                if fn(key,raw_input(each)):
                    break
                else:
                    keep_trying = raw_input("Try again:")
                    if keep_trying.lower() in ['n', 'no', 'naw']:
                        break

    if __name__ == '__main__':
        sample_fields = ("Given Name: ",
                         "Surname: ",
                         "Date of Birth: ",
                         "etc: ")

        example = generic_form(sample_fields)

        print "Fill in my form:"
        form_input(example)

        print
        print "Please review your input:"
        for i, x, x in example.get_hints():
            print example.get(i),

在这个例子中,额外的复杂性并没有做任何有用的事情。我们的generic_form没有进行任何验证。然而,这个输入函数可以与任何提供相同接口的数据/表单类一起使用。在这个例子中,这个接口只需要一个get_hints()方法,提供“提示字符串”、存储键和存储函数引用的元组,以及一个store()方法,必须返回“True”或“False”,并接受要存储的键和数据作为参数。

我们的存储键作为一个不透明的项传递给输入“客户端”,必须通过调用store()方法传回,这一点有点微妙;但它允许我们对多个表单元素使用同一个验证函数……所有名称可以是任何字符串,所有日期必须通过某个time.strftime()调用或某个第三方解析器……等等。

主要的观点是,我可以创建更好的表单类,实施适合收集和存储的数据的验证方法。输入示例适用于我们最初的简单表单,但对于返回有意义结果的表单,效果会更好(表单和输入处理之间更好的接口可能会提供“错误”和“帮助”提示,以及我们在这里展示的简单短“输入”提示。一个更复杂的系统可能会通过get_hints()方法传递“datum”对象。这将要求表单类实例化这样的对象,并存储它们的列表,而不是我在这里展示的元组)。

另一个好处是,我还可以编写其他输入函数(或实现这些函数的类),也可以使用这个相同的接口与任何表单。因此,我可以编写一些HTML渲染和CGI处理,这样可以使用所有已经开发的表单,而无需更改我的数据验证语义。

(在这个例子中,我使用get_hints()方法作为我粗略输出函数和输入的提示。我这样做只是为了保持例子的简单。在实际应用中,我希望将输入提示与输出处理分开。)

撰写回答