2012-01-05 77 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