Member Avatar for Mouche

So my idea for this program was to take data from a file and compiling it into a schedule type thing.... Comments? Again...for learning purposes, I'd love to see suggestions for content, efficiency, and techniques.

# Get data from schedules.txt
import string
f = open("schedules.txt","r")
schedule_rawdata = f.readlines()
f.close()
# Split data into list items
schedule_data = []
for line in schedule_rawdata:
    schedule_data.append(string.split(line,","))
# strip newlines
for line in schedule_data:
    del line[-1]

# Student Class
class Student(object):
    '''Student'''
    def __init__(self, name, age, grade):
        self.name = name
        self.age = age
        self.grade = grade
        self.schedule = {}
        schedule_formatted = ""
        self.address = ""
        self.city = ""
        self.state = ""
        self.zip = ""

    def __compile_schedule(self):
        '''Used for print_schedule()'''
        classes_temp = "" # Classes formatted for showing the schedule
        period_list = ['1A','2A','3A','4A','5A','1B','2B','3B','4B','5B']
        for index in range(5):
            period = period_list[index]
            classes_temp = classes_temp + "| %-3s | %-33s|\n" % (period,self.schedule['A'][index])
        classes_temp = classes_temp + "|" + "-"*40 + "|\n"
        for index in range(5):
            period = period_list[index+5]
            classes_temp = classes_temp + "| %-3s | %-33s|\n" % (period,self.schedule['B'][index])
        classes_final = classes_temp[:-1]
        return classes_final
           

    def get_schedule(self):
        if self.schedule['A']:
            schedule_formatted = self.__compile_schedule()
            self.schedule_formatted = schedule_formatted
        else:
            self.per1a = raw_input("Period 1A class: ")
            self.per2a = raw_input("Period 2A class: ")
            self.per3a = raw_input("Period 3A class: ")
            self.per4a = raw_input("Period 4A class: ")
            self.per5a = raw_input("Period 5A class: ")
            self.per1b = raw_input("Period 1B class: ")
            self.per2b = raw_input("Period 2B class: ")
            self.per3b = raw_input("Period 3B class: ")
            self.per4b = raw_input("Period 4B class: ")
            self.per5b = raw_input("Period 5B class: ")

            self.schedule = {'1a': self.per1a, '2a': self.per2a, '3a': self.per3a,'4a': self.per4a, '5a': self.per5a, '1b': self.per1b, '2b': self.per2b,'3b': self.per3b,'4b': self.per4b, '5b': self.per5b}

    def print_schedule(self):
        name = "Name: " + self.name
        age = "Age: " + self.age
        grade = "Grade: " + self.grade
        address = "Address :"
        city_state_zip = self.city + ", " + self.state + " " + self.zip
        print \
'''
%-23s %s
%-23s %s
%-23s %s
==========================================
| Per | Class                            |
------------------------------------------
%s   
==========================================
''' % (name,address,age,self.address,grade,city_state_zip,self.schedule_formatted)

def add_address(self):
    try:
        self.address = schedule_data[0][3]
    except IndexError:
        pass
    try:
        self.city = schedule_data[0][4]
    except IndexError:
        pass
    try:
        self.state = schedule_data[0][5]
    except IndexError:
        pass
    try:
        self.zip = schedule_data[0][6]
    except IndexError:
        pass

# Declare people from file
person1 = Student(schedule_data[0][0], schedule_data[0][1], schedule_data[0][2])
person1.schedule = {'A':schedule_data[1],'B':schedule_data[2]}
add_address(person1)

person1.get_schedule()
person1.print_schedule()

text file:

Mouche,18,12,1111 SW 1st PL,Dayton,OH,45390,
Underwater Basket Weaving,Concert Band,Lunch,Release,Release,
PE1,PE2,Team Sports,Lunch,Study Hall,

I haven't written it so that it accepts multiple users yet and detects how many people are in the data file. Suggestions for that?

As always, thanks for your time.

Just for form, import your modules, do define your classes and functions, then write the rest of the code lines.

Be judicious with self, it is to be used in classes and their methods. If you use it outside of classes it will confuse you later!

Member Avatar for Mouche

Code error! Ugh. I've worked on this for over 30 minutes and I still can't get it to work. It pulls lines in from a file and saves them to the list. There might be extra empty lines in the file, so it adds those as a slot with just '\n'. I want to delete these slots, and I've tried about 5 different ways. The way shown is going into extra code just to try to make it work. Help, please!

# imports
import string

# Student Class
class Student(object):
    '''Student'''
    def __init__(self, name, age, grade):
        self.name = name
        self.age = age
        self.grade = grade
        self.schedule = {}
        schedule_formatted = ""
        self.address = ""
        self.city = ""
        self.state = ""
        self.zip = ""

    def __compile_schedule(self):
        '''Used for print_schedule()'''
        classes_temp = "" # Classes formatted for showing the schedule
        period_list = ['1A','2A','3A','4A','5A','1B','2B','3B','4B','5B']
        for index in range(5):
            period = period_list[index]
            classes_temp = classes_temp + "| %-3s | %-33s|\n" % (period,self.schedule['A'][index])
        classes_temp = classes_temp + "|" + "-"*40 + "|\n"
        for index in range(5):
            period = period_list[index+5]
            classes_temp = classes_temp + "| %-3s | %-33s|\n" % (period,self.schedule['B'][index])
        classes_final = classes_temp[:-1]
        return classes_final
           

    def get_schedule(self):
        if self.schedule['A']:
            schedule_formatted = self.__compile_schedule()
            self.schedule_formatted = schedule_formatted
        else:
            self.per1a = raw_input("Period 1A class: ")
            self.per2a = raw_input("Period 2A class: ")
            self.per3a = raw_input("Period 3A class: ")
            self.per4a = raw_input("Period 4A class: ")
            self.per5a = raw_input("Period 5A class: ")
            self.per1b = raw_input("Period 1B class: ")
            self.per2b = raw_input("Period 2B class: ")
            self.per3b = raw_input("Period 3B class: ")
            self.per4b = raw_input("Period 4B class: ")
            self.per5b = raw_input("Period 5B class: ")

            self.schedule = {'1a': self.per1a, '2a': self.per2a, '3a': self.per3a,'4a': self.per4a, '5a': self.per5a, '1b': self.per1b, '2b': self.per2b,'3b': self.per3b,'4b': self.per4b, '5b': self.per5b}

    def print_schedule(self):
        name = "Name: " + self.name
        age = "Age: " + self.age
        grade = "Grade: " + self.grade
        address = "Address :"
        city_state_zip = self.city + ", " + self.state + " " + self.zip
        print \
'''
%-23s %s
%-23s %s
%-23s %s
==========================================
| Per | Class                            |
------------------------------------------
%s   
==========================================
''' % (name,address,age,self.address,grade,city_state_zip,self.schedule_formatted)

    # Add the address to the person
    def add_address(self):
        try:
            self.address = schedule_data[0][3]
        except IndexError:
            pass
        try:
            self.city = schedule_data[0][4]
        except IndexError:
            pass
        try:
            self.state = schedule_data[0][5]
        except IndexError:
            pass
        try:
            self.zip = schedule_data[0][6]
        except IndexError:
            pass

#  Menu
def menu():  
    menu = \
    '''
(1) - print current person's name
(2) - print current person's schedule
(3) - quit
Choose a selection: '''
    choice = 0
    choice = raw_input(menu)
    while choice < 1 and choice > 3:
        choice = raw_input(menu)
    if choice == "1":
        print currentperson.name
        return 0
    elif choice == "2":
        currentperson.print_schedule()
        return 0
    elif choice == "3":
        print "Thanks for using the Student Scheduling program."
        return 1
    else:
        print "That's not a choice on the menu."
        return 0

# Get data from schedules.txt
f = open("schedules.txt","r")
schedule_rawdata = f.readlines()
f.close()
# Split data and put it into schedule_data
schedule_data = []
for line in schedule_rawdata:
    schedule_data.append(string.split(line,","))

# strip newlines
for line in schedule_data:
    del line[-1]

# Strip empty lines (those with only '\n')
## ERRORS HERE! INDEX ERROR! blah.
for index in range(len(schedule_data)):
##    print "index:",index # for debugging
##    print "length of index:",len(schedule_data[index]) # for debugging
    if len(schedule_data[index]) == 0:
##        print temp[index] # for debugging; prints the empty lists
        del schedule_data[index] # Error HERE!

# Find number of people
lines = len(schedule_rawdata)

# Declare people from file
num_people = lines/3
person1 = Student(schedule_data[0][0], schedule_data[0][1], schedule_data[0][2])
person1.schedule = {'A':schedule_data[1],'B':schedule_data[2]}
person1.add_address()

# Put people in peoplelist
personlist = []
personlist.append(person1)
currentperson = person1

#Retrieve schedules for people
for person in personlist:
    person.get_schedule()    

# Run menu until user exits
finished = 0
while finished == 0:
    finished = menu()

print schedule_data # why aren't the empty nested lists gone!

It still uses the same text file:

Mouche,18,12,1111 SW 1st PL,Dayton,OH,45390,
Underwater Basket Weaving,Concert Band,Lunch,Release,Release,
PE1,PE2,Team Sports,Lunch,Study Hall,

By the way, I took your advice vegaseat and reorganized my code. Thanks.

Thank you for any help.

Member Avatar for Mouche

phew. It's working. I used this function to remove the empty lists:

def remove_empty_lists(L):
    return [sub for sub in L if sub]

...wha?

Member Avatar for Mouche

It's list comprehension.

[sub for sub in L if sub] means that append sub to the list for each item in L if sub...meaning if sub is true. If 'sub' is an empty list, it doesn't fufill the "if sub" and it's not appended to the list. Thus, you end up with the same list minus empty lists.

Recommendations:

(1) BugFix:

# strip newlines
#old code -- might snip the last line in the file if no newline present
for line in schedule_data:
    
    del line[-1]
# new code -- removes trailing '\n's *and* empty lines all at once!
schedule_data = [line.strip('\n') for line in schedule_data if line.strip('\n')]

(2) Code Clarity:

# old code -- should work fine, but is long
def get_schedule(self):
        if self.schedule['A']:
            schedule_formatted = self.__compile_schedule()
            self.schedule_formatted = schedule_formatted
            self.per1a = raw_input("Period 1A class: ")
            self.per2a = raw_input("Period 2A class: ")
            self.per3a = raw_input("Period 3A class: ")
            self.per4a = raw_input("Period 4A class: ")
            self.per5a = raw_input("Period 5A class: ")
            self.per1b = raw_input("Period 1B class: ")
            self.per2b = raw_input("Period 2B class: ")
            self.per3b = raw_input("Period 3B class: ")
            self.per4b = raw_input("Period 4B class: ")
            self.per5b = raw_input("Period 5B class: ")

            self.schedule = {'1a': self.per1a, '2a': self.per2a, '3a': self.per3a,'4a': self.per4a, '5a': self.per5a, '1b': self.per1b, '2b': self.per2b,'3b': self.per3b,'4b': self.per4b, '5b': self.per5b}
# new code
def get_schedule(self):
        if self.schedule['A']:
            schedule_formatted = self.__compile_schedule()
            self.schedule_formatted = schedule_formatted

# This list could be a class constant
period_list = ['1A','2A','3A','4A','5A','1B','2B','3B','4B','5B']

self.schedule = {}

for i in period_list:
    self.schedule[i] = raw_input("Period %s class: " % i)

(3) Life advice:

Mouche,18,12,1111 SW 1st PL,Dayton,OH,45390,
Underwater Basket Weaving,Concert Band,Lunch,Release,Release, PE1,PE2,Team Sports,Lunch,Study Hall,

Get a real schedule! :p:lol:

Jeff

(Seriously: nice program.)

Member Avatar for Mouche

Thanks a lot for the code clarity change. Those types of things are really what I like to hear from you guys. I want to be an efficient programmer. Learning efficient techniques early on is the way to go...

Get a real schedule! :p:lol:

lol..I changed it for my own privacy for when I posted it on the web. I'm actually taking AP classes and have a 4.0. ;P

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.