In the previous chapter, we took a break from all the learning and creating more fun mini projects. Now that we’re energized, let’s go back to learning for a couple more chapters, shall we?
In this chapter, we’ll be looking at a very interesting concept. We had an introduction to automation in Python using loops, but in this chapter, let’s look at True automation with functions. It works like magic. You’ll see.
True automation
Why do I call it that? We already looked at loops, and they did plenty of automation on their own. We created full-blown shapes with just a few lines of code, am I right? So, why do we need functions?
Well, what if you need to repeat the code? For example, let’s bring back the code we wrote in our loops chapter. Remember how we created a program that creates a shape based on the inputs we give it? We had to run the program multiple times to draw different shapes. What if I want to draw different shapes from the same run of the program? What if I want to give multiple inputs, so my program draws each shape, one after the other, while erasing the previous shape? How would you do that?
You’d probably have to write the same code multiple times, with different inputs for angle and sides, am I right? So, if you wanted to draw five shapes, you need five for loops, one after the other, with a clear() method between each loop. That’s too long! What if we can shorten this as well?
With functions, you certainly can! You can create your “for loop” with something called a “function”. We’ve been using a lot of functions so far. It’s just that, we call them pre-defined methods because they were already created in Python. But now, you can create your own functions. How exciting is that? You’ve become such an experienced programmer that you can now create your own functions, call them, send arguments, automate, and so on.
Now that your “for loop” is within your function, you can do something called “calling the function” and give different values every time to make sure that your for loop draws a different shape every time. I’ll teach you how to do exactly that in just a moment.
But for now, let’s learn how to write a basic function.
Our first function
Every function has two parts. There’s the function definition, which has the code that you want executed multiple times. Then, there’s the function call, which is the line of code that literally “calls” the function definition. It might send arguments/values that serve as input to your function.
But to start with, let’s create a function without arguments so you understand how they work at their base.
So, functions have a definition, don’t they? So far, we’ve noticed that Python is very intuitive. Its syntax makes sense. “if” means the English word If; and “while” means something is going to go on for a while, hence a loop; and so on. Similarly, “def” means you’re creating a function definition.
Just mention “def”, the name of the function you are creating, followed by parenthesis and a colon, as usual. Then, in the next line, add your lines of code after an indent. It’s as simple as that!
Great! We have our function. Let’s run it.
Crickets…nothing happens. ☹ Why?!
Ah right, we haven’t called it yet! How do we do that? Well, how did we call our pre-defined functions? The format is the same. The function’s name, followed by parenthesis. That’s it!
Ahah! We got it.
Why do we need functions?
But what’s the use of a function? I’m confused. Are you? It does what we’ve been doing all the while without adding extra lines of code to create and call the function.
We got it! Or did we? What’s the use of this either? We still created five lines of code. We would have done that anyway. We saved neither time nor space. Bummer!
Do different things every time!
You’ll understand the true use of function when you send different values to it every time you call it. Let’s change our greet() program in such a way that it greets a person every time it calls.
Now that I want the function to greet the person with their name every time, I need to let my function know what their name is, am I right? How do I do that? Maybe my function can receive it while it’s being called? Yes! You can include the name of the parameter or parameters (you can send as many as you want) you send inside of the parenthesis while you create your function.
Okay, pause! Parameter? Argument? Which is which? Not to worry. It’s all the same, really, but if you want to be specific, the values you send from your function call are called parameters, and the values you receive in your function definition are arguments. Simple, right? You’ll understand better once we look at our example.
Create (define) your functions
Look at that! I received the parameter “name” within my parenthesis, and then I used it in my print statement. This is not a variable, per se, but it acts like it. You can name your parameter anything you want. Once we’re done with this example, why don’t you change the name of your parameter from “name” to “n” and see if it still works the same?
Nice! Don’t be confused by the same “name”. I just made the name of the variable and the name of the parameter the function receives the same, so you don’t get confused. But the parameter name can be anything you want, and your program would still work the same.
Look at that! It works!
You can reuse your code!
Now, I’m going to show you the real use of functions. The real use of functions lies in the fact that you don’t need to repeat the same lines of code over and over again.
So, let’s create a function called “calculation” that calculates the addition, subtraction, division, and multiplication of any two numbers it receives. Alright?
In the preceding lines of code, I received the two numbers as the parameters n1 and n2. Then I converted them to integers because I’m going to receive the numbers using the “input()” method, and those values are strings by default. Then, I’ve done the calculations and finally printed everything out using the multi-line string quote.
Now comes the part I was talking about. Now that we’ve created the calculate function, we can call it any time we want. What if we want the calculations done three times? Before we discovered functions, we would have written the same lines of code multiple times because there is no other way to receive different inputs and do the same calculations with different values.
I’ve created three function calls where each of the function calls has two arguments which are nothing more than input statements.
Look at that! With the same few lines of code, I was able to do three different set of calculations without resorting to running the program three times like we usually do.
Now this is the true use of a function. True automation!
No arguments?
The function call is missing one required argument.
The argument is not defined! So, always make sure that the number of arguments matches the number of parameters in the function definition.
Give an answer
So far, we’ve just printed things out. But what if we need an answer? Let’s say I have an expression, and I’m using the add() and mul() functions to get the result of addition and multiplication on my numbers. But then, I want to, let’s say, divide them all. How can I do that when I don’t know the result of the operation? Printing the result isn’t always enough, is it?
Python has a simple solution for this as well! Just return the result. Simple as that. Use the “return” statement, and return your result, and it’ll be received in your function call. Then, you can either assign the function call to a variable and use the result or use the function call as a value in itself.
Confused? Don’t be, my dear. Yet another fun activity is on its way to make you understand the concept.
You’ll save lines of code if you do it like this. This will only work if your entire function just has one line of code.
In the preceding lines of code, I received two numbers as inputs and converted the strings to integers. And then, I created a variable called “calc” which divides the results of the multiplication of those numbers by the addition of those numbers.
Instead of performing the operation on there, I just received the values in the variables mul and add. Technically, this is all we need because the return statements in those functions will return the result of the operations to the function calls, and then they can be used in the “calc” operation.
Yes! It works! Why don’t you try the same with different operations? Make it as complicated as you want to and have Math fun!
No arguments? What to do!
Sometimes, you might not know what arguments to send. Maybe you just want to test the function? But sending no arguments when the function expects arguments will give us an error! What can we do?
Default arguments to the rescue!
You can assign “default” values to your arguments when you define your function, so they work even if you forget to send any arguments when you call your function. Would you like to test it?
It works exactly as we expected. The default argument gets ignored when we actually send an argument from our function call. If we forget, it’s used. Perfect!
Too many arguments!
Function hasn’t stopped making your programming life easy just yet. What if you don’t know how many arguments you’re going to send? But you want to receive all of them, without any error.
Arbitrary arguments will help you do that. Instead of the name of the argument, receive them with *listName and you can access each argument as you’d access a list item. Let me show you how.
Let’s say I want to print the sum of the numbers sent by my function call, but I don’t know how many I’d need added, so I’ll just receive them as an arbitrary argument.
Wow, this single feature gives so much freedom to do whatever I want in my programs!
On the other hand, you can just send a list as an argument. That’ll work too. Why don’t you try modifying the preceding program to send and receive a list of numbers?
Great!
Global vs. local
Look at the preceding program. I’ve created a variable “i” that prints numbers from 1 to 9 in the same line. After the for loop is done, we print a new line and the current value of “i”.
Look at that! It’s 9 and not an error because once the “i” was created, even though it was created inside for loop, it becomes accessible to the entire program.
Variables within functions
Look at the preceding output. Things were fine while the function was still being executed. It printed out our numbers in the order we wanted. But then, when we tried to print the current value of “i” outside the function, we get a “not defined” error. How’s that possible? The variable “i” was defined inside the for loop in the function, was it not?
Yes, it was, but it was local to that function and cannot be used outside. So, any variable created inside of a function is called a local variable.
Return local variables
It works!
Global variables
Similarly, any variable created outside of a function is called a global variable, and if you want to use it inside a function, you need to use the global keyword, like this:
Let’s say I want to create a global variable “sum”. Every time I send a list of numbers, they get added to the “current” value of sum, so we essentially get a sum of multiple lists. How do we do that?
I’ve created a variable “sum” and assigned it a 0 at the start of the program. Next, let me define the function. If I want to use the same “sum” from outside the function, then I need to mention it as “global sum” (without quotes) at the start of the function. It’s always good practice to mention the global variables at the very top of a function definition.
The old value of sum was preserved, and it gets added to the new values sent in the subsequent function calls. Sweet!
Order of creation and usage is very important in Python. Before you call a function, define it. So, the function definition should always be above the function call or you’ll get an error. Similarly, before you use a variable, create it. So, your global variables should be created before the function definitions inside which you want them used.
Lambda
A lambda is an anonymous function. It has no name, it can take any number of arguments, but can only have one line of code. Sounds very simple, doesn’t it? Why would we ever need it when we have our glorious functions to work with?
In the future chapters, we’ll be working with events. These events will let you call functions when you click a button on an app, press your mouse button, click a keyboard button, and so on. Lambdas are very much needed in those cases, so let’s look at them now (even if right now they’re not of much use to us).
Why do we assign our lambda to a variable? So we can call it, of course!
Mini project – do your Math homework with Python
We’re going to make this project simple. If we used a package like Tkinter, we could make this a proper app. But we haven’t covered Tkinter yet, so let’s just do it in the Shell.
- 1.
Different functions for each of the operations – addition, multiplication, division, subtraction, and modulus.
- 2.
We’re going to get input from the user. We’ll be getting two numbers to start with and their choice on which operation they want to perform.
- 3.
Then, we’re going to print the result and ask them if they want to continue using the calculator.
- 4.
If the answer is “y” or “Y”, then we’ll ask them if they want the previous result as one of the numbers in the calculation. If “y” or “Y” for that as well, then we’ll just ask one more input and ask for the operation they want again.
- 5.
The calculator can go on like this forever. When the user answers “n” for continuation, we’ll break out of the loop and end the program.
- 1.Let’s create the functions that do the operations again. Since the function definitions need to be created before they are called, let’s finish that first.#Additiondef add(n1,n2):return n1 + n2#Subtractiondef sub(n1,n2):return n1 - n2#Multiplicationdef mul(n1,n2):return n1 * n2#Divisiondef div(n1,n2):return n1 / n2#Modulusdef mod(n1,n2):return n1 % n2
- 2.
Now, let’s create a never-ending while loop, which means the condition is always true until we break out of the loop with a “break” statement.
- 3.
Inside the while loop, we’ll ask the user to enter the two numbers as inputs and convert the strings to integers as always.
- 4.Then, we’ll ask for the operation. We’ll use an if…elif…else statement to call the relevant function and get the result.#create a result globallyresult = 0 #default valuerepeat = 0 #if the user decided to reuse the result of previous operation, this becomes 1while(True):#if this is the first/new operationif(repeat == 0):#number1num1 = input('Your first number: ')num1 = int(num1)#number2num2 = input('Your second number: ')num2 = int(num2)#If the user asked to use the result of the last operation in this oneelse:#number2num2 = input('Your second number: ')num2 = int(num2)#get the operatorop = input('''Enter any of the following numbers, that correspond to the given operation:Just the number, not the period.1. Addition2. Subtraction3. Multiplication4. Division5. Modulus''')op = int(op)#Call the relevant functionif(op == 1):result = add(num1,num2)elif(op == 2):result = sub(num1,num2)elif(op == 3):result = mul(num1,num2)elif(op == 4):result = div(num1,num2)elif(op == 5):result = mod(num1,num2)else:print('You entered an invalid operation. Please run the program again')break#print the resultprint('Answer: {}'.format(result))again = input('Do you want to do another operation? Enter Y or N: ')if((again == 'y') or (again == 'Y')):reuse = input('Do you want the result of the current operation to be the first number of the next? Y or N: ')if((reuse == 'y') or (reuse == 'Y')):num1 = resultrepeat = 1else:repeat = 0else:print('Ok bye!')break
Mini project – automated shapes – next level
Loops were automation, but functions are supposed to be True automation, aren’t they? Why don’t we see what they can do to our automated shapes mini project?
I’m going to create a function called draw_shape() and place my code inside. I’m going to accept two arguments inside my function: sides and angle.
If the sides are equal to 1, I’m going to draw a circle. Otherwise, I’m going to draw a polygon. Simple as that.
- 1.Let’s import the turtle and time packages first.import turtleimport time
- 2.Then let us set up turtle. I’m going to set the pen color to red and fill color to yellow.s = turtle.getscreen()t = turtle.Turtle()t.pensize(5)t.color('Red','Yellow')
- 3.Then, I’m going to define the draw_shape() function. At the start of the function, I’m going to use the sleep() method of the time package to basically stop the program for 0.3 seconds (300 milliseconds). Then, I’m going to clear the turtle so any previous shape is erased before I draw the next one.def draw_shape(sides,angle):time.sleep(0.3)t.clear()t.begin_fill()#If sides are greater than 1, then it’s a polygonif sides > 1:for x in range(0,sides):if(x == sides-1):t.home()breakt.forward(100)t.right(angle)elif sides == 1:#circlet.circle(100,angle)t.end_fill()t.hideturtle()turtle.hideturtle()
- 4.I’m going to give multiple values in various function calls. When you run this program, you’ll see these shapes drawn in succession, with a 0.3 delay in between.draw_shape(4,90)draw_shape(3,60)draw_shape(5,50)draw_shape(6,60)draw_shape(8,45)draw_shape(1,180)draw_shape(1,360)
Neat!
Summary
In this chapter, we looked at True automation with functions. We learned all about defining functions, calling them, sending arguments to make our functions dynamic, returning values back to the function calls, accepting arbitrary arguments, and so much more. We also automated some of the projects we did in the previous chapters.
In the next chapter, let’s do real-world programming like the pros do it! We’re going to look at objects and imitating real-world scenarios in programming.