2010-05-22 89 views
0

對於我的應用程序,我需要打印出一系列輸出,然後接受來自用戶的輸入。這樣做的最好方法是什麼?在Python中讀取一系列輸入/輸出

像:

print '1' 
x = raw_input() 

print '2' 
y = raw_input() 

這樣的事情,但它會去至少10倍。我唯一擔心的是,它會彌補糟糕的代碼可讀性。

我應該怎麼做?我應該創建這樣一個功能:

def printOut(string): 
    print string 

還是有更好的辦法?

+1

增強將是用戶輸入的readline模塊:http://docs.python.org/library/readline.html – miku 2010-05-22 10:52:30

回答

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()內置函數提供的)是最原始的形式(爲簡單起見,並使用殼重定向處理文件的能力主要是有用的)。人們還可以支持輸入與GNU readline支持(已包含在Python的標準庫),詛咒的支持(也包括在內),以及一個能想象寫一些HTML包裝和CGI代碼,用於處理基於Web的輸入。

如果我們需要或希望支持除「啞終端」以外的任何形式的輸入或輸出,則耦合「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不執行驗證。但是,這個相同的輸入函數可以用於提供相同接口的任何數據/表單類。在這個例子中,該接口只需要一個提供「提示字符串」,存儲鍵和存儲函數引用的元組的方法,並且該方法必須返回「True」或「False」並且爲鍵和數據引用參數被存儲。

事實上,我們的存儲密鑰作爲一個不透明的項目傳遞給我們的輸入「客戶端」,必須通過調用store()方法傳遞給我們的輸入「客戶端」,這有點微妙;但它允許我們使用任何單一的驗證功能,用於多個表單元素......所有的名字可以是任意的字符串,所有日期必須通過time.strftime()一些電話或一些第三方的解析器...等等。

重點是我可以創建更好的表單類,根據收集和存儲的數據實施數據驗證方法。輸入例子我們原來的啞形式的工作,但它的工作與我們的調用返回有意義的結果store()(表單和輸入操作之間的更好的界面可能會提供「錯誤」和「幫助」的形式更好地提示還有簡單的短「輸入」提示我們在這裏展示。一個更復雜的系統可能會通過get_hints()方法傳遞「數據」對象。這將要求forms類實例化這些對象並存儲它們的列表,而不是我在這裏展示的元組)。

另一個好處是,我還可以編寫其他輸入函數(或實現此類函數的類),它們也可以將這個接口用於任何形式。因此,我可以編寫一些HTML渲染和CGI處理,這些處理可以使用所有已開發的表單,而不會更改我的數據驗證語義。 (在這個例子中,我使用get_hints()方法作爲我原油輸出函數的提示以及我的輸入,我只是這樣做來保持這個例子簡單,實際上我想分開輸入提示從輸出處理)。

+0

謝謝你的回覆。 – user225312 2010-05-22 16:33:52

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

感謝您的這一點。 – user225312 2010-05-22 12:02:12

0

「10倍......可憐的代碼的可讀性」

不是真的。你必須提供比這更復雜的東西。

20行代碼幾乎不成問題。您可以輕鬆地編寫超過20行代碼,以避免簡單編寫20行代碼。

您還應該閱讀raw_input的說明。 http://docs.python.org/library/functions.html#raw_input

它寫入提示。你的四行代碼真的是

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

你不能簡化這麼多。

+0

我明白了。我忽略了這個事實。謝謝。 – user225312 2010-05-22 11:58:38