一次读取一行文本文件,一行n行

时间:2014-03-24 12:09:03

标签: python python-3.3 slice

我是Python的新手,并制作了问卷调查计划。有没有办法让程序一次显示一个问题及其选择(下一个多项选择问题不会显示,除非前一个问题得到回答)?

我使用切片来实现这一目标,但我想知道我做的事情是不是很好还是有更好的替代方式?

#opens the file with questions, and is told to read only via 'r'
with open("PythonQ.txt", "r") as f:
#reads the file line by line with 'readlines'
    variable = f.readlines()
#issue was with no slicing, it was reading letter by letter. so
#without the slicing and the split, the questions would not print per question
#the goal by slicing is to get readlines to read per question, not the entire file or first 5 words    
    for line in variable[0:6]:
#this strips the brackets and splits it by commas only, otherwise it will print both       
        question = line.split(',')
#joins elements of the list which are separated by a comma  
        print(", ".join(question))

choice1 = eval(input("\nYour choice?: "))

#sliced for second question. Begins at five to provide room in program between first and second question. 
for line in variable[6:12]:
        question = line.split(',')
        print(", ".join(question))

choice2 = eval(input("\nYour choice?: "))


for line in variable[12:18]:
        question = line.split(',')
        print(", ".join(question))

choice3 = eval(input("\nYour choice?: "))


for line in variable[18:24]:
        question = line.split(',')
        print(", ".join(question))

choice4 = eval(input("\nYour choice?: "))


for line in variable[24:30]:
        question = line.split(',')
        print(", ".join(question))

choice5 = eval(input("\nYour choice?: "))


for line in variable[30:36]:
        question = line.split(',')
        print(", ".join(question))

choice6 = eval(input("\nYour choice?: "))


for line in variable[36:42]:
        question = line.split(',')
        print(", ".join(question))

choice7 = eval(input("\nYour choice?: "))


for line in variable[42:48]:
        question = line.split(',')
        print(", ".join(question))

choice8 = eval(input("\nYour choice?: "))


for line in variable[48:54]:
        question = line.split(',')
        print(", ".join(question))

choice9 = eval(input("\nYour choice?: "))


for line in variable[54:60]:
        question = line.split(',')
        print(", ".join(question))

choice10 = eval(input("\nYour choice?: "))

#add up all the numbers the user typed and assigned it variable x
x = choice1 + choice2 + choice3 + choice4 + choice5 + choice6 + choice7 + choice8 + choice9 + choice10

#there are only so high a person's score can go, depending upon if user chose mostly 1's, 2's, 3's or 4's in quiz.
if x <= 13:
    print("\n\n\nYour personality and work environment type is...\n \n\n\nRealistic: The 'Doer'\n")
#another file was created for the results. Import file. Then call the function, CategoryA.
    import Results
    Results.CategoryA()
elif x <= 22:
    print("\n\n\nYour personality and work environment type is...\n \n\n\nSocial: The Helper\n")
    import Results
    Results.CategoryB()
elif x <= 31:
    print("\n\n\nYour personality and work environment type is...\n \n\n\nEnterprising: The Persuader\n")
    import Results
    Results.CategoryC()
elif x <= 40:
    print("\n\n\nYour personality and work environment type is...\n \n\n\nConventional: The Organizer\n")
    import Results
    Results.CategorD()

2 个答案:

答案 0 :(得分:1)

抱歉,我对你的问题无能为力,但我想要。 我仍然想问:你有9个相同的代码,所以我可以提供我的吗?

你的代码重复:

for line in variable[6:12]:
        question = line.split(',')
        print(", ".join(question))

choice2 = eval(input("\nYour choice?: "))

9次表示循环: 如果我们将“choice1”重命名为“x”

for i in range(1,10)
    for line in variable[6*i:6*(i+1)]:
        question = line.split(',')
        print(", ".join(question))

x+=eval(input("\nYour choice?: "))

我接受所有的批评。

答案 1 :(得分:0)

下面是使用生成器在更多Pythonic习语中完全重写代码。

您的问题是您阅读了整个文件,其中包含六行多项选择问题的测验+答案索引1)。4):variable = f.readlines()variable是比quiz_contents更糟糕的名称选择,但无论如何。

并且您想要分别访问每个6行的多项选择问题和答案。 既然您使用readlines()来访问每个块,那么您必须对','进行奇怪的拆分,然后用','连接(似乎没必要?)然后显示它。

所以不要使用variable = f.readlines()!这会在整个文件中形成一个巨大的多行字符串,在任何地方都没有拆分 - 而不是一系列单独的行(在换行符上拆分),这是你通过连续6次调用readline()得到的。您可以在换行符上split('\n'),但最好是避免首先使用readlines()。相反,请使用readline(),每个问题6次。

所以这是下面代码重写中使用的Pythonic方法:

  • 只需在需要时阅读每个6行块。不需要包含文件内容的巨型字符串缓冲区
  • 请注意print (line, end='') # don't add extra newline
  • 的使用
  • 我们需要某种get_chunk()来返回每个6行的块。在这种情况下,生成器比功能更优雅。它还允许我们检测EOF并返回None。
  • 这使得调用代码更加优雅,因为我们现在只说for chunk in get_chunk(quiz_contents)。当for-loop从生成器
  • 获得None时,它将终止
  • 次要注意:get_chunk()实际上必须为每个块读取6 + 4行 - 每个块中有4个额外的空行。您可以轻松删除它们并添加print(...)。
  • 在生成器内部,我们使用列表推导chunk = [buf.readline() for _ in range(n)]而不是for循环。但你可以使用for循环。 _是一次性变量的惯用Python名称(例如,在这种情况下,我们只需要数到6,否则我们永远不会检查for循环计数器)

__

quiz_file = './PythonQ.txt'
num_questions = 10

def get_chunk(buf, n):
    """Read n-line chunks from filehandle. Returns sequence of n lines, or None at EOF."""

    while buf:
        chunk = [buf.readline() for _ in range(n)]

        if not any(chunk):  # detect termination at end-of-file (list of ['', '',...] )
            chunk = None

        yield chunk

    # Notes:
    # This is a generator not a function: we must use 'yield' instead of 'return' to be able to return a sequence of lines, not just one single line
    # _ is customary Python name for throwaway variable


with open(quiz_file) as quiz_contents: # Note: quiz_contents is now just a filehandle, not a huge buffer. Much nicer.

    choices = [None] * num_questions

    i = 0

    for chunk in get_chunk(quiz_contents, 6+4): # need to read 6 lines + 4 blank lines

        if not chunk:
            break    
        # Don't even need to explicitly test for end-condition 'if i >= num_questions: break'  as we just make our generator yield None when we run out of questions

        print() 
        for line in chunk:
            print (line, end='') # don't add extra newline

        choices[i] = int(input("\nYour choice (1-4)?: ")) # expecting number 1..4. Strictly you should check, and loop on bad input
        i += 1

        # Don't even need to test for end-condition as we'll just run out of questions

    score = sum(choices)
    print('Your score was', score)

    # do case-specific stuff with score... could write a function process_score(score)