5.6 A Special Calculator: Part 1
In this lesson and the next we will create a calculator class that not only supports the common arithmetic functions of a calculator, but can also maintain a history and undo operations.
1.Introduction2 lessons, 11:32
2.Python Building Blocks6 lessons, 1:08:07
3.Controlling the Flow7 lessons, 1:20:10
4.Common Data Structures4 lessons, 46:49
5.Application Structure7 lessons, 1:15:12
6.Collections7 lessons, 46:55
7.File I/O6 lessons, 48:51
8.Networking5 lessons, 43:48
9.Connecting to Network Services3 lessons, 34:27
10.Conclusion1 lesson, 02:08
5.6 A Special Calculator: Part 1
To put the finishing touches on our work here with classes I wanna take you through a bit of an exercise once again to kind of exercise some of these things that we've been learning in writing an actual application or, in this case, at least a class that has some functionality. So here's a bit of a background. What I'd like to be able to create here, now you can definitely follow along with me, or I actually urge you to kind of take these ideas into consideration. And maybe pause the video, and work through it yourself, and then come back and see kind of where we land. Now, I'm not gonna tell you that there's one way to get to the finish line in this case. There's many different ways, and many different variations of this, but whatever feels right to you, whatever feels easiest and most natural to you, is ultimately what I urge you to do. And then, we'll see kind of how we match up at the end. So what I'd like to do is I'd like to create a calculator class. And within this calculator class it should do all of the basic functionality, be able to add a couple of digits together, be able to subtract, multiply and divide. Now we're gonna make an assumption here that we're gonna be mostly working with integer values here. There's some variations that we can talk about during this application, where we can talk about doing integer versus float and kind of going back and forth between the two. But let's just assume we're talking about integers here. So what I'm looking for here is I want to have a calculator that will be able to do that type of functionality that's gonna maintain a running total. And if you think about a calculator that you would, use a physical calculator, or the calculator, say, on your phone or some sort of mobile device. Typically what's gonna happen when you first start it up it's going to start off with a total of zero. That's gonna be kind of your beginning point. And you can start to do things like 5 plus 5. And when you do that it's going to show you the sum, it's going to show you 10. And then you can also, from that point, now that you have 10, you can just hit plus 5 and it's going to give you 15 at that point, right? So it's gonna keep maintaining this kind of running total. And it's also kind of maintaining this concept of not necessarily always needing to take two numbers in, maybe you could just take in one number. And it's going to assume if it only takes in one number that it's going to add that number to the previous total that was running, that it's been keeping track of. Another piece of functionality, that I think might be kind of interesting, is I want this calculator to maintain history. So for each time, that you do something like 5 plus 5, where you input two digits, it's going to reset this history or the memory, or whatever you want to call it, to ground zero, to be empty, to have nothing going on. And then after that, every single time that you do an operation like plus 5, plus 2, times 5, divided by 4, it's going to record that into its internal history and be able to track all of the operations that it's done to so far get to the point of where it's at in calculating its total. And then I want that to be able to be output to the end-user to show them the history, and then ultimately be able to pick one of those operations in that history, remove it, and then have the calculator recalculate its total. So hopefully that makes sense. I'm gonna walk you through how I'm going to do it. Once again, if you want you can pause this and kind of do your own thing and then come back and see where we meet in the end. But, otherwise, you can just work it out with me. So I'm gonna start with the basics here and I'm gonna create my class. So I'm going to create a class and I'm gonna call this calc. You can call it calculator or simple calc or whatever it really doesn't make any difference. And then we're gonna come in here and we're going to create a constructor, so I'm gonna do my __init__ here. And, once again, I'm going to make this an instance method, because basically I want everything that's happening within this instance of the calculator to be specific to it. I don't wanna have to share it across different instances or across the class. I want everything to be instance-specific in this case. So I'm not really going to have anything else come in here at this point. I'm really going to use this to just initialize two things. Remember I want to be working with a total, so I'm going to set the total at this point equal to zero, and then I'm also going to maintain some memory here, or the history or whatever you want to call it. So I'm gonna call it memory so I'll say self.memory is going to be equal to an empty list. And that's what I'm going to use to track all of these operations that are going on within the calculator. So at this point really we can just start knocking out some of the default functionality. We should be able to add, subtract, multiply and divide. And you're gonna find that these methods are gonna be quite similar. One thing to note, though, is, as I said, they have the option of taking in either one or two digits. So we could pass in just one, we could pass in two. And depending on how we do that or depending on how the user uses that we could ultimately be just appending or just adding, subtracting multiplying or dividing a single number with this total that we're working with, or we could be putting two numbers together. I'm gonna show a little trick on how we can do that. We've learned a little bit about it, one part of the step. But I'm going to show you another little trick that we can do that will kinda make this a little bit easier. So I'm gonna first create a method called add. And this is going to be an instance, so I'm gonna pass in this self. And now what I wanna do is I wanna pass in two arguments. So it'll have a and b, or x and y, or whatever have you. Now ultimately what I'm gonna do here is I'm going to start writing this out. But remember I said this could take in one parameter one argument or two. So I'm gonna wanna use a default, like a default value, like we talked about in a previous lesson. But what do we set the default to? How do we really know if the end user passed something in or not? Well, we could do something like equal to zero. But then how are we going to know if the user actually passed in zero, or if they just didn't pass in anything? And that could be kind of a tough distinction there. So really what I wanna do is I want to specify a default value for this second argument, or a third in this case, because it's an instance method. I wanna pass something in here that's going to differentiate itself from being 0. And the way you can do that in Python is by using None. Now None is a special value that just denotes that, there is nothing there. It's kind of like null or nil, or those types of things, if you've ever seen those in other types of programming languages. So now the first thing we wanna do is we wanna know whether or not a value was passed in for that second parameter, that None parameter. And the way that we do that is by saying if b is None. So if nothing was passed in, and it's given the default value of None, and then we're gonna do this operation, which means we're just going to add a to our total. So the way that we'll do that is by saying self.total += a. And then at that point we also want to append this operation onto the memory so that we can recall it later on. So we'll just do something very simple like, self.memory.append. And what do we want to append here? We wanna append what the operation probably looked like. So really if we were just kind of doing this on a regular calculator, it would be something like maybe, +2 is what the operation we would be doing here. So we're gonna append a string here that's gonna look very similar to that. And so we're gonna say, +, and then we're gonna do a little string formatting here, so I can concatenate this information in here, .format. And I'm gonna pass in to this particular argument here, this parameter, the value that was passed in for a, just like that. So now, we've covered the case where they've only passed in a single digit. Now we're gonna do an else here. And we're going to assume in this case that b was passed in, which means we were given two digits. So in this case we're gonna kinda reset everything, the total, to be equal to a + b. So that when we're given two values, we're going to assume that we're gonna reset that total to be whatever that is. And we're gonna start over by this running total. And then also at this point we can kind of keep track of this in our memory. But really this is kind of like a resetting of the memory, if you will. So we'll just do self.memory is going to be equal to a new list. And really, at this point I think this could be probably the end here. We're only gonna be concerned about the operations that were handled in this way, for this particular instance, for the history and being able to kind of go back and remove things. So for this point I think this will do the trick. Now this basic format that we've just created for the add method is going to work basically the same for all of the other operations, subtract, multiply, and divide, with the exception of this operator, and this operator, changing to be either, minus, multiply, or divide. So if you would like to go ahead and just pop that in there. I'm gonna actually stop the recording now and just fill those in, so you don't have to really watch me do that. And then we'll come back, and you can see it when I'm done. Okay, so now I'm back, and as you can see here, I've added in a couple other methods. I've added in subtract, multiply and divide. And the only changes I've really done here is I've changed the operator from a + to a- here, and also in the my memory here. And then for multiply, it's the same thing. I have *, *, and *. And then divide, and doing the same thing, /, /, and /. So now we've got this basic calculator going on where it's keeping a running total, and it's kind of remembering all the operations that we're doing, at least the basic operations. So before we actually go and run this, let's write a little helper method here. Something that is going to output the contents of the memory to the screen, to the end user so they can ultimately see what's been going on. So this is gonna be a very simple method here. We'll just call this, maybe show_memory. And this is going to be an instance method again. And then all we're really gonna do here is we're gonna loop through all the contents of the list that is memory and output them. Just print them to the screen and maybe we'll show the index. So, ultimately, the end user can choose an index to remove something from, should they want to. So we're simply going to do a for statement here. We'll say for indexed in range. So we're gonna use our range function. And we want to find out the length of self.memory. So for all the indexes found within the range created by the length function here. We simply want to do a print statement and we'll do a print of the index. And then maybe we'll throw in there a little colon, and then we'll output the value found there which will be self.memory, and then the index here just like that. So let's go ahead and save that now I've saved that here as calc.py. So let's go ahead and see if we can use this now just to see where we're currently at. So let's go into our interactive shell, and I'm going to say from calc, I want to import calc. And now I'm going to create a new instance so I'll say c = calc. Just like that, everything seems to be working so far, c is an instance of calc. Now let's go ahead and see what our total is, so c.total Is 0, so that's what we want. And then we're also going to check out c.show_memory, like that. So, nothing was returned, so it looks to be that it is empty so far. So let's start to add something in here, so let's say, c.add 5 and 4. So let's see what c.total is now should be nine. Okay, that looks good, c.subtract. So, at this point we just want to say, all right, now we've gotten a total of nine, now let's just subtract from that, say two, so let's subtract two. And if I were to ask for total again, okay we're at seven, that's good. Now if I were to do c.multiply, and I wanna multiply that by 3. Let's check c.total again. Now we're at 21, that looks correct. And then if we were to do c.divide, and wanna divide that by 7, in theory we would have 3. But in actuality we're gonna get 3.0 because remember all division operations are going to result ultimately in a floating point number. So it looks like our basic operations are working. Now, what does our history look like though? So let's go c.show_memory. Okay, so now we have here is we ultimately have a subtract 2, multiply by 3 and divide by 7. Now, this is technically correct. But it's not containing our initial add of these two things together. So I'm going to propose this to you. Now I specifically left these things empty here. Now what I would like for you to do, as an exercise for your own time, I would like for you to find a way to put some information in here, however you would like to do it, into the memory so that you can ultimately show that in the history in some form, and have it work in to your advantage when I show you this next method that we're going to write. And then I'll kind of give you a little tip as to how you might want to do that towards the end.