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.
jon.kiparsky 326 Posting Virtuoso
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?
SgtMe 46 Veteran Poster Featured Poster
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.
ryan461 0 Junior Poster
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?
Edited by ryan461 because: n/a
griswolf 304 Veteran Poster
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:
- You have to define it in the scope of the class definition
- 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....
TrustyTony 888 ex-Moderator Team Colleague Featured Poster
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
Edited by TrustyTony because: n/a
ryan461 0 Junior Poster
Thanks both of yah, that should help get me started.
ryan461 0 Junior Poster
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
griswolf 304 Veteran Poster
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")
Edited by griswolf because: english
ryan461 0 Junior Poster
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 :)
Edited by ryan461 because: n/a
jcao219 18 Posting Pro in Training
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()
ryan461 0 Junior Poster
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
Edited by ryan461 because: n/a
jcao219 18 Posting Pro in Training
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.
Edited by jcao219 because: n/a
ryan461 0 Junior Poster
Hmm...
Change all theshopping.????(self)
toself.????()
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.
Edited by ryan461 because: n/a
jcao219 18 Posting Pro in Training
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.
Edited by jcao219 because: n/a
jcao219 18 Posting Pro in Training
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.
Edited by jcao219 because: n/a
ryan461 0 Junior Poster
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()
Edited by ryan461 because: n/a
ryan461 0 Junior Poster
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
jcao219 18 Posting Pro in Training
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.
Edited by jcao219 because: n/a
ryan461 0 Junior Poster
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.
jcao219 18 Posting Pro in Training
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.
Edited by jcao219 because: n/a
ryan461 0 Junior Poster
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
griswolf 304 Veteran Poster
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
ultimatebuster 14 Posting Whiz in Training
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.
ryan461 0 Junior Poster
Please delete this post. i clicked on the edit/delete button but see no delete.
Edited by ryan461 because: n/a
ryan461 0 Junior Poster
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.
Edited by ryan461 because: n/a
jcao219 18 Posting Pro in Training
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.
Edited by jcao219 because: n/a
ryan461 0 Junior Poster
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
jcao219 18 Posting Pro in Training
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))
Edited by jcao219 because: n/a
ryan461 0 Junior Poster
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.