I've got a couple of pdf's on python, but im having trouble grasping how to build classes. Was trying to do it for a poker program and i think im in over my head with that idea. (its a bit big just doing it with functions). So id like an exercise that can get me into them and understand them more.

Recommended Answers

All 29 Replies

Have you used any other object-oriented languages? In other words, are you looking for help on classes as a concept or on how to do OO in python?

Why don't you make like a text-based shopping checkout program? You can have a main class filled with all the main functions, like a welcome, ouput priter etc.
Then you can have an object class. It can have variables like name, price, quantity, etc. Then you can make new objects using the base class.

Python is basically my first language. I generally get the idea of OO. But looking at examples with def __init__ (self) and such i just get all confused. Coding with a bunch of functions was a lot simpler i found. As i could just call other functions with: name(arg). Here you have to define variables for each method and class, and with the poker thing it was hard to get my head around what id need to define. so something simple is probably a good plan

Why don't you make like a text-based shopping checkout program? You can have a main class filled with all the main functions, like a welcome, ouput priter etc.
Then you can have an object class. It can have variables like name, price, quantity, etc. Then you can make new objects using the base class.

Can you have classes separate from each other and interact? or do i need to set a super class.

Right now ive got for psudo code:

class shopping

def welcome:
    prints welcome to the exotic car store

def makemenu:
    prints Please type the full model, we offer:
    Ferrari, Lamborghini, Porsche

def pricemenu:
    Please type the price range you are looking for:
    50k - 100k, 100k - 250k, 250k - 500k, 500k+

def menu:
    to search by price enter 1
    to search by make enter 2
    if 1:
        pricemenu()
    if 2:
        makemenu()

So i could set a class for the more specific menus for the make and price ranges. But can i reference them from the methods: makemenu and price menu?

Also in terms of code. I need to do:

def __init__(self)

for the class correct? and reference self for each of the methods?

You might look here:
http://wiki.python.org/moin/BeginnersGuide
http://pytut.infogami.com/node11-baseline.html

My own basic take on classes: A class is a description of a data holder along with the things you might want to do to the data, or find out about the data. In Python, you have to be explicit so when you define a class method, you have two things you have to do:

  1. You have to define it in the scope of the class definition
  2. You have to specify a name for the instance of the class, which must be the first parameter to the method. By tradition, that name is 'self' but if you want to be obscure, you may use any name at all (don't do it).

Here is a very simple class that has no specified constructor

class SimpleMessageClass:
  def setMessage(self, message):
     self.message = message
  def printMessage(self):
     if self.message:
        print(self.message)
     else:
        print("Sorry, I have no message")

# now lets exercise the class
# create an instance:
msg = SimpleMessageClass() # default constructor if you don't define one
msg.printMessage()         # what happens without setMessage?
msg.setMessage("Hi")       # so set it
msg.printMessage()         # and now see what happens

#If we wanted to have a constructor, we would use the specially named method __init__

class slightlySmarterMessageClass):
  def __init__(self, message=None): # constructor has both default and specific msg
    if not message:
      message = "Sorry, I have no message"
    self.message = message
  def setMessage(self,message):
    self.message = message
  def printMessage(self):
    print (self.message)  # this time, the constructor did the defaulting
    
# Now you try this one out....

I would read and think deeply article like this and would really do a use case first, maybe a basic. Isolate objects and attributes/methods and code those. __init__ is just to put initial data to attributes, maybe any automatic method call to take care of calculated initializations.

Do some simplest possible code to do yourself case of using inheritance.

I have wide theoretical background with little practice.

Finally with you last program after few successes start thread in DaniWeb to finish it together and learn to do even greater stuff yourself next time, off course:).

One hint from moving from function style of programming:

Use your experience, if you have, of modularization of code. Secondly, it is common to go back to assigning variables (attributes) in functions in more procedural style instead of trowing around return values inside object. Also you can still use modular programming style and code utility functions, preferably in separate module, for reuse. Also it is good idea to modularize the most general classes in separate module to use in other projects for reuse (arguably strength of OO but practically not so simple).

Correct me, if I am wrong, but that is my understanding of the subject. I am learner in this also.

My small tries in OO:
http://www.daniweb.com/forums/post1228880.html#post1228880
http://www.daniweb.com/forums/post1196358.html#post1196358
http://www.daniweb.com/forums/post1229588.html#post1229588

Thanks both of yah, that should help get me started.

class SimpleMessageClass:
  def setMessage(self, message):
     self.message = message
  def printMessage(self):
     if self.message:
        print(self.message)
     else:
        print("Sorry, I have no message")

# now lets exercise the class
# create an instance:
msg = SimpleMessageClass() # default constructor if you don't define one
msg.printMessage()         # what happens without setMessage?
msg.setMessage("Hi")       # so set it
msg.printMessage()         # and now see what happens

I started building my program. and was wondering how the if self.message: would have a variable from setMessage. I tried this code though and got an attribute error. that message is not part of the class

woops. My bad. This is why we need constructors... I was just typing, not actually trying. I should learn. This code works (but :hasattr isn't a good introduction to classes)

class SimpleMessageClass:
  def setMessage(self, message):
    self.message = message
  def printMessage(self):
    if hasattr(self,'message'):
      print(self.message)
    else:
      print("Sorry, I have no message")

haha no worries. my shopping program seems to be goin alright so far. i made a constructor in one class so i can call functions from the other class. so lots of learning :)

woops. My bad. This is why we need constructors... I was just typing, not actually trying. I should learn. This code works (but :hasattr isn't a good introduction to classes)

class SimpleMessageClass:
  def setMessage(self, message):
    self.message = message
  def printMessage(self):
    if hasattr(self,'message'):
      print(self.message)
    else:
      print("Sorry, I have no message")

Just a matter of personal preference, but I when write code like that, I like to make it a property.

class SimpleMessageClass(object):
    @property
    def message(self):
        try:
            return self.__message
        except AttributeError:
            return "No message."
    @message.setter
    def message(self, message):
        self.__message = message
    def printMessage(self):
         print(self.message)

    
a = SimpleMessageClass()

print a.message
a.message = "New message"
a.printMessage()

Alright ive gotten stuck trying to do a back capability. So my program goes into the ferrari menu under the one class. And if i type back, i want it to goto the makemenu method under the shopping class. Here's some code to put it in clearer:

class shopping:
    
    def __init__(self, MakeInstance, basepriceInstance):
        self.make = MakeInstance
        self.baseprice = basepriceInstance

    def makemenu(self):
        model = raw_input("please print make your interested in: ")
        if model == 'Ferrari':
            self.make.Ferrari()
        #there's a few more than ferrari, but its what im testing with.
        if model == 'back':
            shopping.menu(self)
        else:
            print 'not a valid make, try again'
            shopping.makemenu(self)
    
    def menu(self):
        choice = input("For price press 1, make press 2:")
        #exclusding the pricemenu method and if statement
        if choice == 2:
            shopping.makemenu(self)
        else:
            shopping.menu(self)

class Make:
   
"""This shoppingInstance is what i cant get to work. If i set a variable y = shopping() in the shopping class and use: self.make.Ferrari(y), shopping is undefined in the initial y = statement. Ive also done shoppingInstance=None but cannot reset it in the make class"""
     def __init__(self, shoppingInstance, cartInstance=None):
         self.shopping = shoppingInstance
         self.cart = cartInstance

     def Ferrari(self):
         cars = raw_input("Print stuff")
 
         if cars == 1:
             self.cart.additem('car and price')
         #more of these for each car choice
         
         if cars == 'back':
             self.shopping.makemenu()
         #this above here is the back function i want to work.

#called by:

w = Make()
x = baseprice()

start = shopping(w, x)
start.welcome()
start.menu()

#welcome and baseprice menus i omitted

Hmm...
Change all the shopping.????(self) to self.????() And from what I see, your program is impossibly recursive... shopping(Make(shopping( #make instance, then shopping again, etc How are you running it?

EDIT:
Also you are missing some colons and there're some syntax errors.
Just copy and paste the code that you have working in between code tags. It seems like you rewrote it.

Hmm...
Change all the shopping.????(self) to self.????() And from what I see, your program is impossibly recursive... shopping(Make(shopping( #make instance, then shopping again, etc How are you running it?

Its recursive for the purpose of needing to go back in the menu. Otherwise its shopping -> make -> cart(which isnt in my post). Or if you want to order from different sections. shopping -> make ->shopping -> price -> cart

i changed the stuff as you recommended. the inital menu stuff is still good. but in terms of calling Make im still not sure

Yes i did re write it. im doing it on a box with no internet. so i looked at the screen and typed it on this one.

Yes i did re write it. im doing it on a box with no internet. so i looked at the screen and typed it on this one.

I see.
This is a big challenge to help you with, because we don't have the entire code.

Are you sure there is no way you can transfer the code from your other machine to this one that is connected to the internet?
I'm also having trouble understanding what your program does.

I was able to do this:

class shopping:
    
    def __init__(self,  basepriceInstance,makeInstance):
        self.baseprice = basepriceInstance
        self.make = makeInstance

    def makemenu(self):
        model = raw_input("please print make your interested in: ")
        if model == 'Ferrari':
            self.make.Ferrari()
        #there's a few more than ferrari, but its what im testing with.
        if model == 'back':
            shopping.menu(self)
        else:
            print 'not a valid make, try again'
            shopping.makemenu(self)
    
    def menu(self):
        choice = input("For price press 1, make press 2:")
        #exclusding the pricemenu method and if statement
        if choice == 2:
            shopping.makemenu(self)
        else:
            shopping.menu(self)

class Make:
     """This shoppingInstance is what i cant get to work.
     If i set a variable y = shopping() in the shopping class and use:
     self.make.Ferrari(y), shopping is undefined in the initial y = statement.
     Ive also done shoppingInstance=None but cannot reset it in the make class"""
     def __init__(self, shoppingInstance=None, cartInstance=None):
         self.shopping = shoppingInstance
         self.cart = cartInstance

     def Ferrari(self):
         cars = raw_input("Print stuff")
 
         if cars == 1:
             self.cart.additem('car and price')
         #more of these for each car choice
         
         if cars == 'back':
             self.shopping.makemenu()
         #this above here is the back function i want to work.

#called by:
x = object() # baseprice() is missing from this code
w = Make()
start = shopping(x,w)
w.shopping = start
start.menu()

#welcome and baseprice menus i omitted

and get this:

For price press 1, make press 2:1
For price press 1, make press 2:2
please print make your interested in: Ferrari
Print stuffback
please print make your interested in: back
For price press 1, make press 2:2
please print make your interested in: Ferrari
Print stuffback
please print make your interested in: back
For price press 1, make press 2:

But I have to tell you that this isn't the best way you can write your code.

K here's an update to the code. still not all of it, but should be enough to test what im trying to get to work here. if there's an issue with it, let me know. thanks for your help so far

class shopping:
    
    def __init__(self, MakeInstance, basepriceInstance):
        self.make = MakeInstance
        self.baseprice = basepriceInstance
    
    def welcome(self):
        welcome = 'Welcome to the exotic car store. Type back at any time to go back a menu'
        print self

    def makemenu(self):
        model = raw_input("type ferrari, or back to go back a menu: ")
        if model == 'Ferrari':
            self.make.Ferrari()
        #there's a few more than ferrari, but its what im testing with.
        if model == 'back':
            self.menu()
        else:
            print 'not a valid make, try again'
            self.makemenu()
    
    def menu(self):
        choice = input("For make press 2:")
        #excluding the pricemenu method and if statement
        if choice == 2:
            self.makemenu()
        else:
            self.menu()

class Make:
   
"""This shoppingInstance is what i cant get to work. If i set a variable y = shopping() in the shopping class and use: self.make.Ferrari(y), shopping is undefined in the initial y = statement. Ive also done shoppingInstance=None but cannot reset it in the make class"""
     
     def __init__(self, shoppingInstance, cartInstance=None):
         self.shopping = shoppingInstance
         self.cart = cartInstance

     def Ferrari(self):
         cars = raw_input("Type back to test")
 
         if cars == 'back':
             self.shopping.makemenu()
         #this above here is the back function i want to work.
         
         


class baseprice():
    
    def fifty(self):
        cars = raw_input("text")


w = Make()
x = baseprice()

start = shopping(w, x)
start.welcome()
start.menu()

Ive done some line by line debugging. and when it goes to the back statement under def Ferrari. It does goto the other functions in shopping. But it appears that the variables such as choice is already set to 2. and model is set to ferrari. as it goes straight to those if statements each time

In my opinion, the way you are writing your program has some unnecessary complexities. There is an easier way.

Take a look at this example program I quickly wrote down after thinking about your program structure:

class Car(object):
    def __init__(self,name,price):
        self.name = name
        self.price = price
    def special_menu(self):  #ideally, this should be part of the Shop class, but this is
                             #to be an example of making 'back' go back
        paint = raw_input("What color paint? (Type 'back' to cancel.): ")
        if paint.lower() == "back":  #Observe, no need to reference the shop class
            return False
        else:
            print "Whoops.  Our painter is on strike."
            print "We'll charge you for the paint anyways."
            self.price += 10000
            return True
            
#Object Oriented Programming!
#the_cars is a list which contains two
#Car objects.  These are two objects!
#You can visualize that they are real cars
the_cars = [Car("Ferrari",50000),
            Car("Toy Truck",5)]


class Cart(object):
    def __init__(self):
        self.items = []
    def add_item(self,item):
        self.items.append(item)
        print item.name + " added to cart."


class Shop(object):
    def __init__(self, cars_available=[]):
        self.cars = cars_available
        self.cart = Cart()  #Cart and Shop can also be combined to one class
    def menu(self,shopper):
        print "Welcome {0}".format(shopper.name)
        
        while True:
            if not self.cars:
                print "Out of cars!"
                return
            for choice,car in enumerate(self.cars):
                choice += 1
                print "{0}: {1}".format(choice, car.name)
            purchase_choice = raw_input("Type number that you want: ")
            try:
                chosen = self.cars[int(purchase_choice)-1]
                if chosen.special_menu():
                    self.add_to_cart(chosen)
                else:
                    continue
                shopper.wallet_money -= chosen.price
            except IndexError:
                print "We don't have that car number!"
                continue
            except ValueError:
                print "Please enter numbers only."
                continue

            continue_shopping = raw_input("Continue shopping? (Y/N):")
            if continue_shopping.upper() == "N":
                break
    def add_to_cart(self,item):
        self.cart.add_item(item)
        self.cars.remove(item)
    def add_car(self,name,price):
        self.cars.append(Car(name,price))

class Shopper(object):
    def __init__(self, name, cash):
        self.name = name
        self.wallet_money = cash

the_shop = Shop(the_cars)
me = Shopper("Mr. Shopper", 1000000)
the_shop.menu(me)

Try to make and use classes somewhat like that.

Ok. i think i did get a way for it to work. but i do agree its getting complex and lots of loops. Ill take a look at your approach later and go from there. thanks.

Ok. i think i did get a way for it to work. but i do agree its getting complex and lots of loops. Ill take a look at your approach later and go from there. thanks.

A friendly hint though, you may not be quite grasping object-oriented yet.
It's not merely a matter of code organization,
it's a matter of relating to the real world.
Pretend you have a box of mints.
I really need you to visualize it, as if it were in front of you.
Visualizing it, you see that all mint boxes have these attributes:

  • Brand
  • Price
  • Flavor
  • Amount of Mints
  • Color
  • Weight in grams

So then you create that object:

class MintBox(object):
    def __init__(self, brand, price, flavor, amount, boxcolor, weight):
        self.brand = brand
        self.price = price
        self.flavor = flavor
        self.amount = amount
        self.boxcolor = boxcolor
        self.weight = weight
        self.opened = False

the_mint_box_in_front_of_me = MintBox(
    "Altoids", #brand
    "$2.00", #price
    "peppermint", #flavor
    75, #amount
    "red and white", #boxcolor
    60) #weight in grams

But of course, this newly created mint box is just there.
It can't do anything.
You want to open it and eat a mint!
So you add methods:

class MintBox(object):
    def __init__(self, brand, price, flavor, amount, boxcolor, weight):
        self.brand = brand
        self.price = price
        self.flavor = flavor
        self.amount = amount
        self.boxcolor = boxcolor
        self.weight = weight
        self.opened = False
    def describe(self):
        return "{4} box of {3} {0} \
{2}-flavored mints that costed {1}, and the box also \
weighs {5} grams.".format(self.brand,
                          self.price,
                          self.flavor,
                          self.amount,
                          self.boxcolor,
                          self.weight)
    def open_box(self):
        self.opened = True
        print "You have opened the "+self.describe()

    def eat_one(self):
        if self.amount > 0:
            self.amount -= 1
            print "You have eaten one of the mints inside of this box."
            print "There are now {0} mints left here.".format(self.amount)
        else:
            print "This box is empty!"



the_mint_box_in_front_of_me = MintBox(
    "Altoids", #brand
    "$2.00", #price
    "peppermint", #flavor
    75, #amount
    "red and white", #boxcolor
    60) #weight in grams

print "This is a "+the_mint_box_in_front_of_me.describe()+"\n"
#Now open it of course!
the_mint_box_in_front_of_me.open_box()
#Take one out and eat it!
the_mint_box_in_front_of_me.eat_one()

Hopefully that is a good example for the object-oriented paradigm.

Yeah that does help understand it some more. I'll work on this some more tomorrow and let yah know how it goes. brain has retired for today :p

Also, you need to think about an interactive loop: If you have menu items and want to be able to pop up from one item back to the menu again, you should think about operating in a loop (very little) like this, rather than trying to figure out all possible choice paths:

status = 'top-of-menu'
while true:
  status = printMenuAndGetNewStatus(status)
  if status = 'do-a-ferrari':
    do_a_ferrari()
  elif status = 'do-a-chevy':
    do_a_chevy()
  elif status = 'paint-my-car':
    paint_car()
  else: # break for the 'stop' menu item, but also for bugs
    print 'quitting with status %s'%status
    break

Try making a small text based game that involves a person buying and selling stuff. Seems like it would practice a lot of classes things, and others as well.

Please delete this post. i clicked on the edit/delete button but see no delete.

Well jcao your help has been quite helpful. I've restructured what i was trying to do and designed it much more like your example. I took out the listing by price, made it a little more complex than it needed it to be. so just stuck with manufacturing.

What id like for it to do now tho, is print the cart in a tidly fashion. Right now it prints like:

Ferrari California              $192000
Lamborghini Murcielago LP670-4 SV                $450000

What id like:

Ferrari California                     $192000
Lamborghini Murcielago LP670-4 SV      $450000
Lamborghini Reventon                  $1250000

here's my cart class that does all this, and what ive attempted basically.

Also side question, what does specifying a class as an object change?

#i added an extra value to the cars, to seperate make and model. Theres more then what # i have here.

the_cars = [Car("Ferrari","california",192000), Car("Lamborghini","Gallardo             560-4",201000)]

class Cart(object):

    def __init__(self):
        self.items = []

    def __add_item(self, item):
        self.items.append(item)
        print item.make+' '+item.model+" added to cart."

    def checkout(self):
        print 'Hope you enjoyed your shopping experience.'
        subtotal = 0
        format = "%5s %20s"
        for item in self.items:
            print format % (item.make+' '+item.model, '$'+str(item.price))
            subtotal += item.price
       
        print 'Subtotal: $'+str(subtotal)
        # ill probably line up subtotal, tax, and total as well once i get the 
        # items lined up.

For the formatting, you can do this:

for item in self.items:
    print "{0:26} ${1:>}".format(item.make+' '+item.model,item.price)

Also,
Doing this class MyClass(object) makes MyClass a new-style class,
which is a type of "type."
Old style classes ( class OldStyleClass: )
are a type of "classobj."

Old style classes only exist for compatibility reasons.
You should only use new-style, because old-style will someday go away.
This is part of the unification of types and classes, a relatively advanced topic
I won't get into.

For the formatting, you can do this:

for item in self.items:
    print "{0:26} ${1:>}".format(item.make+' '+item.model,item.price)

yeah that works well. i did find stuff like that for text. but it had the format numbers, the text, then .format. so couldnt get that work obviously.

it lines up like:

$100
$1000

curious if theres a way to line up the back like:

$100
$1000

thanks again, youve been helpful

I'm working on the formatting syntax,
right now I have this,

for item in self.items:
    print "{0.make} {0.model:20} ${0.price}".format(item)

but I can't get it to format correctly, so this will have to do:

for item in self.items:
    print "{0:20} {1:>10}".format(" ".join((item.make, item.model)),'$'+str(item.price))

I'm working on the formatting syntax,
right now I have this,

for item in self.items:
    print "{0.make} {0.model:20} ${0.price}".format(item)

but I can't get it to format correctly, so this will have to do:

for item in self.items:
    print "{0:20} {1:>10}".format(" ".join((item.make, item.model)),'$'+str(item.price))

works just fine, thanks.

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.