Struggling with classes

This is the place for queries that don't fit in any of the other categories.

Struggling with classes

Postby älgkött » Tue Feb 19, 2013 9:52 pm

Hello,

This is my first post. I'm struggling with a school project which include classes.
Basically I want to read some data from a file (I think i manage this part) and then receive input from the user. The file contains names of casinos and entry fees for adults and children and also maximum number of visitors.
The data from the file and the input should then result in some analysis like total revenues for each casino and also in total for all casinos.

The program should work for several casinos and I think I should use classes. My problem is that I don't know how to access the data from my class Casino to, lets say, a definition Analysis which do the calculations.
I also want some kind of input definition were the user enter the number of sales for each casino. The I want the data from the file and the input from the user to result in the analysis, like total revenues, number of total tickets sold, vacancy rate etc.

I this the right approach?

text file wrote:Atlanta
5
1
200

Reno
4
1
150


Code: Select all
import re
import copy

#Creates a new casino depending on my textfile

class Casino (object):
    def __init__(self,name,adult,child,maximum):
        self.name=name              #name of casino (string)
        self.adult=adult            #entry fee adult(float)
        self.cild=child             #entry fee child(float)
        self.maximum=maximum        #maximum number of visitors(float)


def Read(filename):
    file=open(filename,'r')
    thelist=[]
    name=file.readline().strip()
    while name:
        adult=float(file.readline().strip())
        child=float(file.readline().strip())
        maximum=float(file.readline().strip())
        add_casino=Casino(name,adult,child,maximum)
        empty=file.readline()
        thelist.append(add_casino)
        name=file.readline().strip()
    return thelist

def inputs(thelist):
    print("""
                Enter sales for the casinos:
            """)
    i=0
    for add_casino in thelist:
        i+=1
        print (' ' + str(i) + ' ' +add_casino.name)
    sales=[]
    sales=input('Enter first adult then child:')

def analysis(thelist):
   
    adults=[]
    for add_casino in thelist:
        adults=(add_casino.adult)
    print(adults)
   
    vacancy=sales/adults




def main(): 
    thelist=Read("casino.txt")
    inputs(thelist)
    analysis(thelist)

main()
Attachments
casino.txt
text file
(44 Bytes) Downloaded 42 times
casino_p.txt
program
(1.46 KiB) Downloaded 78 times
Last edited by stranac on Tue Feb 19, 2013 10:14 pm, edited 3 times in total.
Reason: Added code tags and stuff
älgkött
 
Posts: 6
Joined: Sun Feb 17, 2013 6:29 pm

Re: Struggling with classes

Postby ichabod801 » Tue Feb 19, 2013 10:28 pm

The basic idea is okay, but you're not making full use of the class. I would put your inputs and analysis functions into the class as methods (like __init__ is right now). Right now you're not doing anything with the sales data being input. If it was a method of the class it could easily store the data in the appropriate class. Then the analysis method would have access to the information for calculations.

Also, if I understand what you're doing, your vacancy calculation is wrong. It seems to be dividing sales (which you don't have because you didn't return it from inputs and then pass it to analysis) by the cost for an adult. The adult sales divided by the adult cost would be the number of adults, and the number of children could be similarly calculated. Add those together and subtract from maximum occupancy to get vacancy.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 84
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

Re: Struggling with classes

Postby älgkött » Sun Feb 24, 2013 7:42 pm

Thanks for the input!

I have worked with the code and hopefully I'm on the right track.

To be clear, I want my program to do these things:
1. read from text file the basic facts about my casinos, different entry fees and maximum capacity
2. take input from user about the latest sales
3. calculate and present total revenues for each casino with occupancy rate, and also total revenues for all casinos
4. the program should be able to handle additional casinos added in the text file without much tinkering with the code

Questions:
How can i store all my sales in a total sales variable?

Is it better if the user enters the sales in a list or string? Lets say I want 10 different levels of entry fees, then my current solution will generate a lot of code. So any ideas how I can do this more effectively?

Final question, just for my understanding, how can I print or access the list I create in def read? I don't really know how this list looks like because I don't know how to print it.

Code: Select all
# textfile:
# atlanta
# 5
# 1
# 200
#
# reno
# 4
# 1
# 150
#
# MGM
# 5
# 4
# 1000



import re
import copy

#Creates a new casino depending on my textfile

totalrevenue=0

class Casino (object):
    def __init__(self,name,adult,child,maximum):
        self.name=name              #name of casino (string)
        self.adult=adult            #entry fee adult(float)
        self.child=child             #entry fee child(float)
        self.maximum=maximum        #maximum number of visitors(float)
       

    def __str__(self):
        return self.name + "/" + str(self.adult)+ "/" + str(self.child) + "/" + str(self.maximum)


    def returnName(self):
        return self.name

    def analysis(self,soldA,soldC):
        revenueA=self.adult*soldA
        revenueC=self.child*soldC
        revenueTot=revenueA+revenueC
        occupancy=(soldA+soldC)/self.maximum
        print('Total revenues for',self.name,'amounts to $',revenueTot)
        print('This corresponds to a ',occupancy*100,'% occupancy rate')

       
    def showinfo(self):
        print('Name:',self.name)
        print('Ticket price adult:',self.adult)
        print('Ticket price child:',self.child)
        print('Maximum capacity:',self.maximum)
        return


def read(filename):
    file=open(filename,'r')
    thelist=[]
    name=file.readline().strip()
    while name:
        adult=float(file.readline().strip())
        child=float(file.readline().strip())
        maximum=float(file.readline().strip())
        add_casino=Casino(name,adult,child,maximum)
        empty=file.readline()
        thelist.append(add_casino)
        name=file.readline().strip()
    return thelist


def enterSales(thelist):
    ready=False
    while not ready:
        showItems(thelist)
        answer=input('Choose casino:')
        if answer:
            index=int(answer)-1
            add_casino=thelist[index]
            add_casino.showinfo()
            salesA=float(input('Enter sales for adults in '+ add_casino.returnName()+':'))
            salesC=float(input('Enter sales for children in '+ add_casino.returnName()+':'))
            add_casino.analysis(salesA,salesC)
        else:
            ready=True


def showItems(thelist):
    print('You have these casinos to report sales for:')
    i=0
    for add_casino in thelist:
        i+=1
        print(' '+str(i)+'.'+add_casino.name)
    print('(Press enter for meny)')
   

def meny(thelist):
    print('Welcome to the casino sales program!')
    ready=False
    while not ready:
        print('1. Enter sales')
        print('2. See statistics')
        answer=input('Enter choise:')
        if answer=="1":
            enterSales(thelist)
        elif answer=="2":
            stats=thelist[0]
            stats.showinfo()
        else:
            ready=True


def main(): 
    thelist=read("casino.txt")
    meny(thelist)
   


main()
älgkött
 
Posts: 6
Joined: Sun Feb 17, 2013 6:29 pm

Re: Struggling with classes

Postby ichabod801 » Mon Feb 25, 2013 12:32 am

älgkött wrote:How can i store all my sales in a total sales variable?


The analysis method of the Casino class needs to either return or store the revenueTot. That is, the analysis method should end either with 'return revenueTot' or 'self.revenueTot = revenueTot'. I would do the first if you just need to use the revenue total once, the second if you want to use it more than once. Actually, since you are calculating more than one thing in analysis, I would probably use the second version to store each calculated value.

älgkött wrote:Is it better if the user enters the sales in a list or string? Lets say I want 10 different levels of entry fees, then my current solution will generate a lot of code. So any ideas how I can do this more effectively?


Ten different pay levels looks to generate ten lines of code. That doesn't strike me as that much.

älgkött wrote:Final question, just for my understanding, how can I print or access the list I create in def read? I don't really know how this list looks like because I don't know how to print it.


Well, you've got a couple of options already coded, since your Casino class has the __str__ and showinfo methods. You could just loop through the list with a for loop, printing the result of __str__ or calling show info for each casino. Another thing is that when you print a list, it prints the repr() of each item in the list. So if you gave your Casino class a __repr__ method just like the string one, you could just print theList and that would take of it.

BTW, theList is fine when you have one list. But in any vaguely serious project you'll end up with more than one list, and you'll have theList, theOtherList, yetAnotherList, and so on. A better name would be casinoList. It may not matter much here, but it's a good habit to get into.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 84
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

Re: Struggling with classes

Postby älgkött » Thu Feb 28, 2013 8:57 pm

Thanks for the help ichabod. I think I solved the printing of all casinos with my while loop and my total revenue also seem to work.

My problem now is that I don't know how to "store" or keep my occupancy levels while running the program. I want to be able to enter sales for one or all of the casinos and then go to the statistics part and see all the different casinos with their individual occupancy rate (depending on sales the user puts in)

Now, all my occupancy levels are equal to zero because I'm using my Casino class again, which states self.occupancy=0. The reason I want my occupancy levels to be unique for each casino is that I later on want to present the statistics depending on the occupancy level. Will it be possible to use some kind of sort(list) function with my current setup?

Code: Select all
# textfile:
# atlanta
# 5
# 1
# 200
#
# reno
# 4
# 1
# 150
#
# MGM
# 5
# 4
# 1000



import re
import copy

#Creates a new casino depending on my textfile


class Casino (object):
    totalrevenue=0
    def __init__(self,name,adult,child,maximum):
        self.name=name              #name of casino (string)
        self.adult=adult            #entry fee adult(float)
        self.child=child             #entry fee child(float)
        self.maximum=maximum        #maximum number of visitors(float)
        self.revenueTot=0
        self.occupancy=0

    def __str__(self):
        return self.name + "/" + str(self.adult)+ "/" + str(self.child) + "/" + str(self.maximum)
       

    def __repr__(self):
        return


    def returnName(self):
        return self.name

    def analysis(self,soldA,soldC):
        revenueA=self.adult*soldA
        revenueC=self.child*soldC
        revenueTot=revenueA+revenueC
        occupancy=(soldA+soldC)/self.maximum
       
        print('\nTotal revenues for',self.name,'amounts to $',revenueTot)
        print('This corresponds to a ',occupancy*100,'% occupancy rate')
        Casino.totalrevenue+=revenueTot
       

       
    def showinfo(self):
        #print('\n____Statistics for your casinos!___\n')
        print('\nName:',self.name)
        print('Ticket price adult:',self.adult)
        print('Ticket price child:',self.child)
        print('Maximum capacity:',self.maximum)
        print('Current occupancy rate:',self.occupancy,'%')
        return

    def totalRev(self):
        print('\nTotal revenues for all casinos:',Casino.totalrevenue)
        return


def read(filename):
    file=open(filename,'r')
    thelist=[]
    name=file.readline().strip()
    while name:
        adult=float(file.readline().strip())
        child=float(file.readline().strip())
        maximum=float(file.readline().strip())
        add_casino=Casino(name,adult,child,maximum)
        empty=file.readline()
        thelist.append(add_casino)
        name=file.readline().strip()
    return thelist


def enterSales(thelist):
    ready=False
    while not ready:
        showItems(thelist)
        answer=input('\nChoose casino:')
        if answer:
            index=int(answer)-1
            add_casino=thelist[index]
            add_casino.showinfo()
            salesA=float(input('\nEnter sales for adults in '+ add_casino.returnName()+':'))
            salesC=float(input('Enter sales for children in '+ add_casino.returnName()+':'))
            add_casino.analysis(salesA,salesC)
        else:
            ready=True


def showItems(thelist):
    print('\nYou have these cinemas to report sales for:')
    i=0
    for add_casino in thelist:
        i+=1
        print(' '+str(i)+'.'+add_casino.name)
    print('(Press enter for meny)')
   

def meny(thelist):
    print('Welcome to the cinema sales program!')
    ready=False
    while not ready:
        print('\n1. Enter sales')
        print('2. See statistics')
        answer=input('\n Enter choise:')
        if answer=="1":
            enterSales(thelist)
        elif answer=="2":
            i=0
            while i<=2:
                stats=thelist[i]
                stats.showinfo()
                i+=1
            stats.totalRev()
        else:
            ready=True


def main(): 
    thelist=read("casino.txt")
    meny(thelist)
   


main()




älgkött
 
Posts: 6
Joined: Sun Feb 17, 2013 6:29 pm

Re: Struggling with classes

Postby ichabod801 » Fri Mar 01, 2013 1:59 pm

älgkött wrote:Thanks for the help ichabod. I think I solved the printing of all casinos with my while loop and my total revenue also seem to work.

My problem now is that I don't know how to "store" or keep my occupancy levels while running the program. I want to be able to enter sales for one or all of the casinos and then go to the statistics part and see all the different casinos with their individual occupancy rate (depending on sales the user puts in)

Now, all my occupancy levels are equal to zero because I'm using my Casino class again, which states self.occupancy=0. The reason I want my occupancy levels to be unique for each casino is that I later on want to present the statistics depending on the occupancy level. Will it be possible to use some kind of sort(list) function with my current setup?


You are using Casino.totalRevenue to store the revenue total across casinos. That's a class attribute. But each instance also has instance attributes. Those are the ones you are setting in the __init__ method: name, adult, child, maximum, revenueTot, and occupancy. As you noted, you already have occupancy set at 0. You just need to set it to the calculated occupancy in the analysis method:

Code: Select all
    def analysis(self,soldA,soldC):
        revenueA=self.adult*soldA
        revenueC=self.child*soldC
        revenueTot=revenueA+revenueC
        self.occupancy=(soldA+soldC)/self.maximum
       
        print('\nTotal revenues for',self.name,'amounts to $',revenueTot)
        print('This corresponds to a ',self.occupancy*100,'% occupancy rate')
        Casino.totalrevenue+=revenueTot


Note that I changed both references to 'occupancy' to 'self.occupancy'. Now you're occupancy rates are stored and can be retrieved later with something like:

Code: Select all
add_casino.occupancy


You can store revenueTot the same way. If you want to sort by occupancy, there are a couple ways to do it. The easy way to do it is with the key parameter of the sort function:

Code: Select all
thelist.sort(key = lambda x: x.occupancy)


The key parameter takes a function of one parameter that returns the value to sort on. The lambda syntax is just a quick way to specify a temporary function. The above is basically the same as:

Code: Select all
def get_occupancy(casino):
    return casino.occupancy

thelist.sort(key  = get_occupancy)


Note that when we pass get_occupancy to the sort method, we don't put a set of parentheses after it. We're passing the function itself, not the result of the function.

The hard way to sort by occupancy is with operator overloading. I intended to do a tutorial that goes into the detail of it, but I'll give a short version of it here. If you don't understand use the key parameter I showed you above.

Just as you have overridden __str__ and __repr__ for your Casino class to change how casinos are treated as text, you can change how casinos are treated in comparisons:

Code: Select all
    def __lt__(self, other):
        return self.occupancy < other.occupancy


Overriding __lt__ (less than) means that now you can use casinos with a < symbol:

Code: Select all
casino_a < casino_b


would now return true if casino_a's occupancy was lower than casino_b's occupancy. You can likewise override <= (__le__), == (__eq__), != (__ne__), > (__gt__), and >= (__ge__). If you override all ofthem, then your lists will automatically sort by occupancy. Now overriding all of them is a pain, but there's a shortcut:

Code: Select all
import functools

@functools.total_ordering
class Casino(object):
    ...


total_ordering is a decorator, which modifies how your class is constructed. In the case of total_ordering, if you define __eq__ and one of __le__, __lt__, __ge__, or __gt__, then total_ordering will define all of the other comparison methods for you.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 84
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

Re: Struggling with classes

Postby älgkött » Fri Mar 01, 2013 7:51 pm

Wow, Thanks! That was a true aha-moment for me.
älgkött
 
Posts: 6
Joined: Sun Feb 17, 2013 6:29 pm


Return to General Coding Help

Who is online

Users browsing this forum: stranac and 2 guests

cron