2012-01-05 70 views
3

這可能會測量pythonic是如何。我在玩耍,試圖學習Python,所以我不接近pythonic足夠。 infile是一個虛擬的父系,我想要一個父親的兒子名單。打印數值的pythonic方式

INFILE:

haffi jolli dkkdk lkskkk lkslll sdkjl kljdsfl klsdlj sdklja asldjkl 

代碼:

def main(): 
    infile = open('C:\Users\Notandi\Desktop\patriline.txt', 'r') 
    line = infile.readline()    
    tmpstr = line.split('\t') 
    for i in tmpstr[::2]: 
     print i, '\t', i + 1 
    infile.close() 
main() 

的問題是i + 1;我想在每行中打印出兩個字符串。這是清楚的嗎?

+6

downvoting和不評論爲什麼,有什麼可怕的習慣... – juliomalegria 2012-01-05 22:23:54

+2

@julio:非常真正。 upvoted至少補償一點。 – 2012-01-05 22:25:13

+2

在這種情況下,你只是僥倖避開它,但單引號和雙引號的Python字符串中的反斜槓引入了轉義碼。如果文件名是,例如'another.txt','\ a'會被轉換成不可打印的字符,並且文件不會打開。養成加倍反斜槓的習慣,或者對Windows文件路徑使用r前綴原始字符串('r「C:\ blahblah \ whatever.txt」)。即使在Windows上,您也可以在文件路徑中使用正斜槓。 – 2012-01-05 23:06:40

回答

6

您在分割字符串中的單詞和它們的索引之間感到困惑。例如,第一個字是「haffi」,但第一個指標是0

遍歷兩個指數及其對應的話,用枚舉:

for i, word in enumerate(tmpstr): 
    print word, tmpstr[i+1] 

當然,這看起來凌亂。更好的方法是迭代字符串對。有很多方法可以做到這一點;這是一個。

def pairs(it): 
    it = iter(it) 
    for element in it: 
     yield element, next(it) 

for word1, word2 in pairs(tmpstr): 
    print word1, word2 
+0

這太棒了。 – voithos 2012-01-05 23:06:52

1

你的文件讀取和打印都可能更加pythonic。試試這個:

def main(): 
    with open('C:\Users\Notandi\Desktop\patriline.txt', 'r') as f: 
     strings = f.readline().split('\t') 
    for i, word in enumerate(strings): 
     print "{} \t {}".format(word, strings[i+1:i+2]) 
main() 

使用strings[i+1:i+2]保證了IndexError沒有拋出(而不是,返回[])試圖在列表的最後到達i+1個索引時。

+0

您可以在閱讀後立即關閉「f」。據我所知,沒有理由要等到'print'循環之後。 – voithos 2012-01-05 22:41:39

+0

你是對的,謝謝。我用''with'聲明清理了它。 – ash 2012-01-05 22:58:55

+0

不錯。另外,我只注意到'.format()'的大量用法!我認爲你必須在大括號內指定索引,但我想現在可以隱式確定它。 – voithos 2012-01-05 23:16:05

0

這裏有一個乾淨的方式來做到這一點。當餵食奇數個物品時,它具有不會崩潰的優點,但當然您可能更喜歡這種情況的例外情況。

def main(): 
    with open('C:\Users\Notandi\Desktop\patriline.txt', 'r') as infile: 
     line = infile.readline() 
     previous = None 
     for i in line.split('\t'): 
      if previous is None: 
       previous = i 
      else: 
       print previous, '\t', i 
       previous = None 

我不會說任何聲稱這是pythonic雖然。

2

我會用在這裏的講話使用,如果你使用python的舊版本,你需要導入:

from __future__ import with_statement 

爲實際的代碼,如果你能負擔得起加載整個文件到內存的兩倍(即,它是非常小的),我這樣做:

def main(): 
    with open('C:\Users\Notandi\Desktop\patriline.txt', 'r') as f: 
     strings = f.read().split('\t') 
    for father, son in zip(string, string[1:]): 
     print "%s \t %s" % (father, son) 
main() 

這樣,你跳過具有開銷太大了不包括在結束無子女的葉子,這是思考的最後一行是什麼你問(?)

作爲一點切線:如果文件非常大,您可能不想將整個內容加載到內存中,在這種情況下,您可能需要一個生成器。如果你實際上打印了所有東西,你可能不需要這樣做,但是如果這是問題的一些簡化版本,這就是我如何使用發生器來分割文件的方法:

class reader_and_split(): 
    def __init__(self, fname, delim='\t'): 
     self.fname = fname 
     self.delim = delim 
    def __enter__(self): 
     self.file = open(self.fname, 'r') 
     return self.word_generator() 
    def __exit__(self, type, value, traceback): 
     self.file.close() 
    def word_generator(self): 
     current = [] 
     while True: 
      char = self.file.read(1) 
      if char == self.delim: 
       yield ''.join(current) 
       current = [] 
      elif not char: 
       break 
      else: 
       current.append(char) 

生成器的值是,在文件上運行拆分之前,不會將文件的全部內容加載到內存中,這對於非常大的文件來說可能很昂貴。爲了簡單起見,此實現僅允許使用單個字符分隔符。這意味着所有你需要做的,解析出一切是使用發電機,一個快速骯髒的方式做到這一點是:

with reader_and_split(fileloc) as f: 
    previous = f.next() 
    for word in f: 
     print "%s \t %s" % (previous, word) 
     previous = word