0

好的,我会尽力提供尽可能多的信息,以便有时间给我一些建议的人更容易做到这一点,希望你们中的一个好人能够帮助我。

我正在编写一个算术训练类的程序。该程序的想法是用户创建一个“会话”,他们指定他们想要的数学运算(/,*,-,+),方程的数量,数字生成器的范围(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 列表,遍历它并打印出每一位数据,然后遍历 equations_data 列表,它是 session_data 列表中的元素 7,记住 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

但是这不起作用,基本上我无法弄清楚如何访问 equations_data 列表中的列表,即 self.session_data [7],但是当尝试迭代这个时,我返回了一个索引错误。

就像我说的那样,我想一一显示每个会话:

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

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

4

1 回答 1

3

为什么将变量放在单个列表属性中?为什么不将它们全部设为类属性,以便您可以按名称而不是编号访问它们?例如, self.equations_data, self.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)方法 inSession将类实例中的数据按照你想要的格式放入一个字符串中,例如:

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不会按照您的意愿运行。在继续之前,您应该阅读有关 Python 类的信息,因为您对它们做出了一些不正确的假设。如果你想在没有实例的情况下访问它们,你必须声明静态方法@staticmethod,我不认为这很 Pythonic。

2&3。使用re而不是嵌套if语句,例如:

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

4. 查看Python 的样式指南并适当地格式化您的代码。它将帮助您开始以 Python 方式编写更多内容,这将使您的代码更清晰、更好。

这些是引起我注意的事情

于 2012-04-24T05:41:01.923 回答