有关python对象和嵌套列表的问题

时间:2012-04-24 04:48:55

标签: python

好的,我会尽量提供尽可能多的信息,让有时间给我一些建议的人更容易,希望你们中的一个好人能够帮助我。

我正在编写一种算术训练程序。该程序的想法是用户创建一个'会话',他们指定他们想要的数学运算(/,*, - ,+),方程的数量,数字生成器的范围(2个数字,例如,如果它们指定1和5,随机化方程的所有数字都在此范围内。)。

然后会话生成并且用户完成方程式,最后用户可以检查他的答案,并显示准确率百分比,完成会话所花费的时间以及会话创建的确切日期和时间。

程序是以面向对象的编程编写的,每个会话都是一个对象。这些对象包含在一个被腌制的列表中。这个想法是用户可以回顾之前的会话并跟踪他们的改进或其他任何事情。

问题: 我有一个不可能的时间迭代每个对象并打印出所有数据。

我的程序代码如下:

import pickle,time,random

class Session:
    def __init__(self,amount,operation,numgen_range):
        start_time = [int(time.strftime('%M', time.gmtime())),int(time.strftime('%S', time.gmtime()))]
        ID = main.get_id() + 1
        accuracy = 0
        rights = 0
        equations_data = []
        duration = [0,0]
        datetime = time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())
        self.session_data = [ID,amount,operation,numgen_range,datetime,accuracy,rights,equations_data,duration]
        main.save_id()

        if self.session_data[2] == '+':
            for i in range(self.session_data[1]):
                a = random.randint(self.session_data[3][0],self.session_data[3][1])
                b = random.randint(self.session_data[3][0],self.session_data[3][1])
                answer = a + b
                user_answer = int(input('{0} + {1} = '.format(a,b)))
                if answer == user_answer:
                    rightwrong = True
                    self.session_data[6] += 1
                else:
                    rightwrong = False
                eq_data = [a,self.session_data[2],b,answer,user_answer,rightwrong]
                self.session_data[7].append(eq_data)
        elif self.session_data[2] == '*':
            for i in range(self.session_data[1]):
                a = random.randint(self.session_data[3][0],self.session_data[3][1])
                b = random.randint(self.session_data[3][0],self.session_data[3][1])
                answer = a * b
                user_answer = int(input('{0} * {1} = '.format(a,b)))
                if answer == user_answer:
                    rightwrong = True
                    self.session_data[6] += 1
                else:
                    rightwrong = False
                eq_data = [a,self.session_data[2],b,answer,user_answer,rightwrong]
                self.session_data[7].append(eq_data)
        elif self.session_data[2] == '-':
            for i in range(self.session_data[1]):
                a = random.randint(self.session_data[3][0],self.session_data[3][1])
                b = random.randint(self.session_data[3][0],self.session_data[3][1])
                answer = a - b
                user_answer = int(input('{0} - {1} = '.format(a,b)))
                if answer == user_answer:
                    rightwrong = True
                    self.session_data[6] += 1
                else:
                    rightwrong = False
                eq_data = [a,self.session_data[2],b,answer,user_answer,rightwrong]
                self.session_data[7].append(eq_data)
        elif self.session_data[2] == '/':
            for i in range(self.session_data[1]):
                a = random.randint(self.session_data[3][0],self.session_data[3][1])
                b = random.randint(self.session_data[3][0],self.session_data[3][1])
                answer = a / b
                user_answer = int(input('{0} / {1} = '.format(a,b)))
                if answer == user_answer:
                    rightwrong = True
                    self.session_data[6] += 1
                else:
                    rightwrong = False
                eq_data = [a,self.session_data[2],b,answer,user_answer,rightwrong]
                self.session_data[7].append(eq_data)

        end_time = [int(time.strftime('%M', time.gmtime())),int(time.strftime('%S', time.gmtime()))]
        if start_time[0] >= end_time[0]:
            self.session_data[8][0] = start_time[0] - end_time[0]
        else:
            self.session_data[8][0] = end_time[0] - start_time[0]
        if start_time[1] >= end_time[1]:
            self.session_data[8][1] = start_time[1] - end_time[1]
        else:
            self.session_data[8][1] = end_time[1] - start_time[1]

        self.session_data[5] = (self.session_data[6] / self.session_data[1]) * 100
        print('You got {0} problems correct out of {1}, your accuracy percentage was {2}%.\nYou took {3} minutes and {4} seconds to complete the session.'.format(self.session_data[6],self.session_data[1],int(self.session_data[5]),self.session_data[8][0],self.session_data[8][1]))

        while True:
            try:
                i = int(input('Enter 1 to check answers or 2 to return to the menu: '))
                if i == 1:
                    main.util = True
                    for i in self.session_data[7]:
                        if i[5]:
                            rw = 'CORRECT'
                        else:
                            rw = 'INCORRECT'
                        print('{0} {1} {2} = {3} Your Answer: {4} - {5}\n'.format(i[0],i[1],i[2],i[3],i[4],rw))
                elif i == 2:
                    main.util = False
                    pass
                else:
                    raise ValueError
                break
            except ValueError:
                print(main.input_error_msg)
                continue

with open('data/saved_sessions.txt','rb') as file:
    saved_sessions = pickle.load(file)

class main:
    util = None
    input_error_msg = 'You entered an invalid input, try again.'

    def create():
        print('Create Session.')

        while True:
            try:
                amount = int(input('Enter the amount of equations you want: '))
                if amount < 1:
                    raise ValueError
                if amount > 50:
                    print('Sorry, the limit for equation amounts is 50, try again.')
                    continue
                break
            except ValueError:
                print(main.input_error_msg)
                continue

        while True:
            try:
                operation = input('Enter operation: ')
                if operation == '':
                    print('You must specify an operation for the session!')
                    continue
                if len(operation) != 1:
                    print(main.input_error_msg)
                    continue
                if "+" not in operation:
                    if "-" not in operation:
                        if "*" not in operation:
                            if "/" not in operation:
                                print("You failed to enter a valid equation type. Please try again.")
                                continue
                break
            except ValueError:
                print(main.input_error_msg)
                continue

        numgen_range = [0,0]
        while True:
            try:
                numgen_range[0] = int(input('Enter base range number: '))
                if numgen_range[0] < 0:
                    raise ValueError
                break
            except ValueError:
                print(main.input_error_msg)
                continue

        while True:
            try:
                numgen_range[1] = int(input('Enter ceiling range number: '))
                if numgen_range[1] < numgen_range[0]:
                    print('Sorry the ceiling range number cannot be larger than the base range number.')
                    continue
                break
            except ValueError:
                print(main.input_error_msg)
                continue

        while True:
            try:
                i = int(input('Enter 1 to generate this session or 2 to enter new specifications: '))
                if i == 1:
                    saved_sessions.append(Session(amount,operation,numgen_range))
                    main.pickle_sessions()
                    if main.util:
                        main.menu()
                    else:
                        main.menu(rmenu=True)
                elif i == 2:
                    main.create()
                else:
                    raise ValueError
                break
            except ValueError:
                print(main.input_error_msg)
                continue

    def get_id():
        try:
            with open('data/id_count.txt','rb') as file:
                count = pickle.load(file)
        except IOError:
            pass
        else:
            return count

    def save_id():
        try:
            with open('data/id_count.txt','wb') as file:
                pickle.dump(ID,file)
        except IOError:
            pass
        else:
            print('id count pickled.')

    def view_archive():
        print('View Session Archive')
        #view archive code to go here.    

    def menu(rmenu=False):
        if rmenu:
            while True:
                try:
                    i = int(input('Enter 1 to return to the menu: '))
                    if i == 1:
                        main.menu()
                    else:
                        raise ValueError
                    break
                except ValueError:
                    print(main.input_error_msg)
                    continue
        else:
            print('Menu -[1]Create Session.[2]View Session Archive.[3]Exit.')
            while True:
                try:
                    i = int(input('Enter choice: '))
                    if i == 1:
                        main.create()
                    elif i == 2:
                        main.view_archive()
                    elif i == 3:
                        quit()
                    else:
                        raise ValueError
                    break
                except ValueError:
                    print(main.input_error_msg)
                    continue

    def pickle_sessions():
        try:
            with open('data/saved_sessions.txt','wb') as file:
                pickle.dump(saved_sessions,file)
        except IOError:
            pass
        else:
            print('Sessions have been pickled.')

    def start():
        if __name__ == '__main__':
            main.menu()

main.start()

现在我要做的是,迭代每个对象,进入它的session_data列表,迭代它并打印出每一位数据,然后遍历在sessions_data列表中的元素7的equations_data列表,保持请注意,Equations_data中填充了更多列表,其中包含每个单独的等式的数据,所以我想迭代它。

总结一下: 打印出每个对象的所有数据。

I thought something like:
for i in saved_sessions:
    for y in i.session_data:
        #print out elements then loop over equations_data on line below
        for x in i.session_data[7]:
            #print out elements

然而,这不起作用,基本上我无法弄清楚如何访问等式数据列表里面的列表,这是self.session_data [7],但是当试图迭代这个im返回时带有索引错误。< / p>

就像我说的我想要做的一个一个地显示每个会话,如:

ID: 1
Date: some date
Time: some time
Operation: +
Equations: 5
Right Answers: 5
Accuracy: 100%
Time Taken: 15 seconds

Equations:
1 + 5 = 6 Your Answer: 6
1 + 6 = 7 Your Answer: 7
1 + 7 = 8 Your Answer: 8
1 + 8 = 9 Your Answer: 9
1 + 9 = 10 Your Answer: 10

对此问题的任何帮助都将非常感激。此外,我非常热衷于对编程的各个方面进行一些残酷的诚实反馈。鼓励建设性的批评。

1 个答案:

答案 0 :(得分:3)

为什么要将变量放在单个列表属性中?为什么不将它们设为所有类属性,以便您可以通过名称而不是数字访问它们?例如,self.equations_dataself.accuracy等?

嵌套循环的问题在于它太嵌套了。你正在迭代i.session_data[7] n次,其中n显然是9,即session_data的长度。你想要的东西是:

for i in saved_sessions:
    for j in range(len(i.session_data)):
        if j!=7:
            y=i.session_data[j]
            # print out your elements here
    for x in i.session_data[7]:
        #print out elements

但是不要这样做。修改你的方法,这样你就不会在那个列表中保存属性。至少将它们存储在字典中,以便您可以按名称访问它们。更好的是,将它们存储为类的属性。

至于打印出你的课程,你应该在__str__(self)中实现Session方法,将类实例中的数据按照你想要的格式放入一个字符串中,例如:

class Session(object):
    ...
    def __str__(self):
        out = 'ID:%s\nAMOUNT:%d ... '%(self.ID, self.amount, ...)   # And so on.
        return out

这样你就可以执行:

for session in saved_sessions:
    print str(session)

就是这样。多么可爱! (仅供参考,在使用for ... in进行循环时,使用描述性词语为变量名更加Pythonic。)

其他建议

  1. 正如@David Robinson所指出的那样,您的班级Main将无法按您的意愿运行。在继续之前你应该read about Python classes,因为你对它们做了一些不正确的假设。如果你想在没有实例的情况下访问它们,你必须用@staticmethod声明方法静态,我不认为这是非常Pythonic。
  2. 2和3。使用re代替嵌套的if语句,例如:

    if not re.search(r'[\*\-\+\/]', operation):
        # Invalid operation, you should raise an exception here
        raise ValueError
    

    4。查看the style guide for Python并正确设置代码格式。它将帮助您开始更多地编写Python,这将使您的代码更清晰,更好。

    那些引起我注意的事情