| Store | Cart

Re: [Tutor] Using Class Properly - early beginner question

From: Mats Wichmann <m...@wichmann.us>
Wed, 22 Mar 2017 21:56:11 -0600
On 03/22/2017 06:30 AM, Rafael Knuth wrote:
> thanks for your feedback! @boB> > I wrote a function that does exactly what I want, and that is:> Create a shopping list and then let the user decide which items (food)> are supposed to be instantly consumed and which ones stored.> > def ManageFood():>     create_shopping_list = []>     prompt = ("Which foods would you like to purchase?\nEnter 'quit' to exit. ")>     food = input(prompt)> >     while food != "quit":>         create_shopping_list.append(food)>         food = input(prompt)> >     print("These are your foods on your shopping list: %s." % ", "> .join(create_shopping_list))>     eat_food = []>     store_food = []>     for food in create_shopping_list:>         print("You bought this item: %s. " % (food))>         prompt = input("What would you like to do with it?\nEnter> 'eat' or 'store'. ")>         if prompt == "eat":>             eat_food.append(food)>         elif prompt == "store":>             store_food.append(food)>     print("Food you want to eat now: %s." % ", " .join(eat_food))>     print("Food you want to store: %s." % ", " .join(store_food))> > ManageFood()> > PS: Please let me know if you have any suggestions how to write my> code above in a shorter, more elegant fashion (it does what it's> supposed to do, but not sure if a pro would write it same way I did).

You could think here about how you described the food items: they have
an attribute which is either eat or store... it's not just a (string)
name, but also how you intend to categorize tht tiem.  It's possible a
dictionary - a collection of name/value pairs - could be a more natural
way to capture the data than multiple lists. So perhaps a datastructure
like:

{ ('asparagus', 'eat'), ('beans', 'store'), ... }

Up to you, just an observation.

> > Besides that, I want to take it a step further and rewrite the> function above as a class, and I don't know how exactly how to do> this.> (coding newbie pains ... I just learned the basics about classes in> Python, but nowhere could I find examples of how to properly> initialize classes, given that it operates solely with user input -> same goes with with calling that class properly). Here's how far I got> on my own:

Rule 1: Python is not specifically an object-oriented language. If the
problem you're trying to solve is best served by a class-based approach,
by all means, it will work fine that way.  But there's nothing /forcing/
you (unless it's a learning assignment, that is: "how do I do this using
classes") to turn an implementation into a class.

After that thought, what do you want the class to represent? The whole
shopping cart? A single food item?  The latter actually feels a bit more
natural to me, but I'm not the one inventing the problem.

On to some details.

> > class FoodShopping(object):>     def __init__ (self, create_shoppping_list, prompt, food, eat_food,> store_food):>         self.create_shopping_list = create_shopping_list>         self.prompt = prompt>         self.food = food>         self.eat_food = eat_food>         self.store_food = store_food

(a) you can store the prompt in the instance, sure, but the prompt is
neither unique to the instance (which means it doesn't need to be
there), nor is it really anything to do with the class, which means it
doesn't really need to be a class variable either.
(b) see above: eat vs store isn't really two different things, it's one
- and maybe it's a boolean: eat = True vs eat = False. Though you might
think of other states later, and then it's not a boolean any more.
(c) probably what you wanted here was not to pass in the three list
items, but to initialize them. And the other parameters perhaps aren't
really things needed up front, so you might even end up with an
initializer that looks like this:

    def __init__(self):
        self.create_shopping_list = []
        self.eat_food = []
        self.store_food = []

Like magic that would fix the initial error your program stopped on -
the initializer wanted multiple args and didn't get them (see below).

>     def ManageFood(self, create_shopping_list, prompt, food, eat_food,> store_food):>         create_shopping_list = []>         prompt = ("Which foods would you like to purchase?\nEnter> 'quit' to exit. ")

This makes no sense... you're passing in "prompt", but then overriding
it in the method. So why pass it in at all?

>         food = input(prompt)> >         while food != "quit":>             create_shopping_list.append(food)>             food = input(prompt)> >         print("These are your foods on your shopping list: %s." % ", "> .join(create_shopping_list))>         eat_food = []>         store_food = []

You already created instance variables create_shopping_list, eat_food
and store_food.  Don't redo those in the method, use the instance
variables (self.create_shopping_list, self.eat_food, self.store_food).

>         for food in create_shopping_list:>             print("You bought this item: %s. " % (food))>             prompt = input("What would you like to do with it?\nEnter> 'eat' or 'store'. ")>             if prompt == "eat":>                 eat_food.append(food)>             elif prompt == "store":>                 store_food.append(food)>         print("Food you want to eat now: %s." % (eat_food))>         print("Food you want to store: %s." % (store_food))

all those references (create_shopping_list, eat_food, store_food) need
to be self.x instead of x

> > FoodShopping()

This line creates an instance of the class.  You need to do something
with that instance object or it's just lost... typically something like:

shopping = FoodShopping()

Then, to the error: the call to instantiate the class causes, after the
actual construction is done, the initializer (__init__) method to be
called. You declared that method to take six arguments, one of which is
the implied instance reference (self), so you need to supply the other
five arguments to the call to instantiate - that's how Python is set up.

Python isn't, say C# - where everything has to happen inside a class
definition, even the main method that causes the real work to happen. A
class definition does no actual work, it just causes a class object to
be created, and a reference to that object to be assigned to the name
you gave the class.  Then when you "call" the class through that
variable, the work starts happening.

> > That's the error message I get when executing my code:> > Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900> 32 bit (Intel)] on win32> Type "copyright", "credits" or "license()" for more information.>>>>> == RESTART: C:/Users/Rafael/Documents/01 - BIZ/PYTHON/Python Code/PPC_29.py ==> Traceback (most recent call last):>   File "C:/Users/Rafael/Documents/01 - BIZ/PYTHON/Python> Code/PPC_29.py", line 140, in <module>>     FoodShopping()> TypeError: __init__() missing 5 required positional arguments:> 'create_shoppping_list', 'prompt', 'food', 'eat_food', and> 'store_food'

And in the end, your program does nothing... you instantiate a class,
then don't save any reference to the instance object that will be
created, which means it will just be lost (no reference -> garbage
collected).  And you have a method in the class  which does all the
interesting work, but the method is never called.

I know this is a lot of comments without providing a actual fix of the
code, but maybe after thinking about some of this stuff you'll come back
with a new iteration we can comment on.

Good luck!



_______________________________________________
Tutor maillist  -  Tut...@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Recent Messages in this Thread
Rafael Knuth Mar 21, 2017 05:20 pm
boB Stepp Mar 22, 2017 02:48 am
Rafael Knuth Mar 22, 2017 12:30 pm
boB Stepp Mar 23, 2017 02:49 am
boB Stepp Mar 24, 2017 09:41 pm
Alan Gauld via Tutor Mar 25, 2017 01:32 am
boB Stepp Mar 25, 2017 03:08 am
boB Stepp Mar 24, 2017 09:42 pm
Alan Gauld via Tutor Mar 25, 2017 01:40 am
boB Stepp Mar 25, 2017 03:14 am
Mats Wichmann Mar 23, 2017 03:56 am
Alan Gauld via Tutor Mar 23, 2017 09:58 am
Messages in this thread