© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2021
A. ElumalaiIntroduction to Python for Kids https://doi.org/10.1007/978-1-4842-6812-4_13

13. Automate with Functions

Aarthi Elumalai1  
(1)
Chennai, Tamil Nadu, India
 

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? ../images/505805_1_En_13_Chapter/505805_1_En_13_Figc_HTML.gif

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

../images/505805_1_En_13_Chapter/505805_1_En_13_Figa_HTML.jpg

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!

Let’s create a function that prints ‘Hello there!’ when we call it. We name our functions so we can call them later on. We’ve called many pre-defined functions like len() and join(), right? The concept is the same for the functions you create: the user-defined functions. I’m going to name my function greet() because that’s what it’s going to do, greet the person who calls it. ../images/505805_1_En_13_Chapter/505805_1_En_13_Figd_HTML.gif
def greet():
    print('Hello there!')

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!

Let’s do things properly now. A function definition, followed by a function call, just like it should be.
def greet():
    print('Hello there!')
greet()
Run the program now, and you’ll get this:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/functions.py
Hello there!

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.

Well…what if I want to greet my user five times and not one time. Maybe there are five people in the group? Before now, I would have added five print statements. But now, I can just add five function calls, like this, and the function will be called, and “Hello there!” would be printed every single time. Cool!
greet()
greet()
greet()
greet()
greet()
Run the preceding code, and you’ll get this:
= RESTART: C:/Users/aarthi/AppData/Local/Programs/Python/Python38-32/functions.py
Hello there!
Hello there!
Hello there!
Hello there!
Hello there!

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

Let’s see how that works:
def greet(name):
    print('Hello {}!'.format(name))

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?

Now that we’ve created our definition, let’s create the rest of the program. Let’s create a variable name and get the input. Then, let’s call the greet() function, but this time with the name of the argument “name” inside the parenthesis.
name = input("What's your name?")
greet(name)

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.

Run the preceding code and you’ll get this:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py
What's your name? Susan
Hello Susan!

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?

So, it’s going to receive two numbers, n1 and n2, as parameters. I’m going to do the calculations and print the results in four separate lines:
def calculate(n1,n2):
    n1 = int(n1)
    n2 = int(n2)
    add = n1 + n2
    sub = n1 - n2
    div = n1 / n2
    mul = n1 * n2
    print('''Addition: {}
Subtraction: {}
Multiplication: {}
Division: {}
          '''. format(add,sub,mul,div))

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.

But now, we have a way!
calculate(input("Enter the first number"),input("Enter the second number"))
calculate(input("Enter the first number"),input("Enter the second number"))
calculate(input("Enter the first number"),input("Enter the second number"))

I’ve created three function calls where each of the function calls has two arguments which are nothing more than input statements.

Let’s run those:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py
Enter the first number 10
Enter the second number 5
Addition: 15
Subtraction: 5
Multiplication: 50
Division: 2.0
Enter the first number 5
Enter the second number 10
Addition: 15
Subtraction: -5
Multiplication: 50
Division: 0.5
Enter the first number 100
Enter the second number 20
Addition: 120
Subtraction: 80
Multiplication: 2000
Division: 5.0

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?

But be careful while sending arguments in your function calls. If you don’t send the number of arguments your function definition is expecting, you’ll end up with an error while running the function. This holds true if you send lesser number of arguments or more arguments.
def greet(name):
    print('Hello {}!'.format(name))
For the above function:
greet()
a call with no argument will give this error:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py
Traceback (most recent call last):
  File "C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py", line 3, in <module>
    greet()
TypeError: greet() missing 1 required positional argument: 'name'

The function call is missing one required argument.

A call two arguments on the other hand:
greet(name1,name2)
You’ll receive the following error:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py
Traceback (most recent call last):
  File "C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py", line 3, in <module>
    greet(name1,name2)
NameError: name 'name1' is not defined

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.

Let me first create two functions, addition() and multiply(). They receive parameters n1 and n2, respectively, and perform addition and multiplication of the two numbers.
def addition(n1,n2):
    add = n1 + n2
def multiply(n1,n2):
    mul = n1 * n2
But I can’t use these values, can I? So, let me return them.
def addition(n1,n2):
    add = n1 + n2
    return add
def multiply(n1,n2):
    mul = n1 * n2
    return mul
Now, I’ve returned the results of the addition and multiplication of the numbers. Alternatively, you can just perform the operation in the return statement, like this:
def addition(n1,n2):
    return n1 + n2
def multiply(n1,n2):
    return n1 * n2

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.

Alright, now that we have our functions ready, let’s use them!
num1 = input("Enter your first number: ")
num1 = int(num1)
num2 = input("Enter your second number: ")
num2 = int(num2)
mul = multiply(num1,num2)
add = addition(num1,num2)
calc = mul /add
print("{} / {} = {}".format(mul,add,calc))

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.

Shall we check if this works?
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32functions.py
Enter your first number: 10
Enter your second number: 5
50 / 15 = 3.3333333333333335

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! ../images/505805_1_En_13_Chapter/505805_1_En_13_Fige_HTML.gif

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?

In the following example, I’ve created a printName function that just prints out the given name. I’ve called the function twice, once with an argument and once without. Let’s see what happens.
def printName(name='Susan'):
    print('My name is {}'.format(name))
printName('John')
printName()
Run, and:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
My name is John
My name is Susan

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! ../images/505805_1_En_13_Chapter/505805_1_En_13_Figf_HTML.gif

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.

Since *listName is essentially a list, we can loop through it like we would in a list.
def addNums(*nums):
    sum = 0
    for num in nums:
        sum += num
    return sum
Let me call my function with my arbitrary arguments now.
print(addNums(1,5,3,7,5,8,3))
print(addNums(1,3,5,7,9))
print(addNums(1,2,3,4,5,6,7,8,9))
When I run the program, I get this:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
32
25
45

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?

Did you try? Did it look something like this?
def addNums(nums):
    sum = 0
    for num in nums:
        sum += num
    return sum
print(addNums([1,5,3,7,5,8,3]))
print(addNums([1,3,5,7,9]))
print(addNums([1,2,3,4,5,6,7,8,9]))

Great! ../images/505805_1_En_13_Chapter/505805_1_En_13_Figg_HTML.gif

Global vs. local

So far, we’ve seen that once you create a variable, you can’t re-define it. You can re-assign values to it, yes, for example:
for i in range(1,10):
    print(i,end='')
print()
print(i)

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”.

Let’s run the program, and we’ll get this:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
123456789
9

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

But that’s not the case with functions. Let’s create the same inside a function now:
def printNum():
    for i in range(1,10):
        print(i,end='')
printNum()
print()
print(i)
Run the above, and:
>>>
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
123456789
Traceback (most recent call last):
  File "C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py", line 7, in <module>
    print(i)
NameError: name 'i' is not defined

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

If you want to use it outside of a function, you need to return it, like this:
def printNum():
    for i in range(1,10):
        print(i,end='')
    return i
i = printNum()
print()
print(i)
Now, run the program, and you’ll get this:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
123456789
9

It works! ../images/505805_1_En_13_Chapter/505805_1_En_13_Figh_HTML.gif

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.

That’s it. The rest of the program is similar to the one we wrote before.
sum = 0
def addNums(nums):
    global sum
    for num in nums:
        sum += num
    return sum
print(addNums([1,5,3,7,5,8,3]))
print(addNums([1,3,5,7,9]))
print(addNums([1,2,3,4,5,6,7,8,9]))
Run this code, and you’ll get the following:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
32
57
102

The old value of sum was preserved, and it gets added to the new values sent in the subsequent function calls. Sweet!

Note

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?

../images/505805_1_En_13_Chapter/505805_1_En_13_Figb_HTML.jpg

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).

A lambda’s syntax is quite simple:
variable = lambda arguments: line of code

Why do we assign our lambda to a variable? So we can call it, of course!

Let’s look at an example now:
sum = lambda num1,num2: num1 + num2
Now, we can call the lambda by calling sum(), like this:
print(sum(3,5))
print(sum(100,240))
Run the preceding lines of code, and you’ll get this:
= RESTART: C:UsersaarthiAppDataLocalProgramsPythonPython38-32condition.py
8
340

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.

Our calculator is going to be designed like this:
  1. 1.

    Different functions for each of the operations – addition, multiplication, division, subtraction, and modulus.

     
  2. 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. 3.

    Then, we’re going to print the result and ask them if they want to continue using the calculator.

     
  4. 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. 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.

     
Interesting? Excited to get started? Me too! ../images/505805_1_En_13_Chapter/505805_1_En_13_Figi_HTML.gif
  1. 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.
    #Addition
    def add(n1,n2):
        return n1 + n2
    #Subtraction
    def sub(n1,n2):
        return n1 - n2
    #Multiplication
    def mul(n1,n2):
        return n1 * n2
    #Division
    def div(n1,n2):
        return n1 / n2
    #Modulus
    def mod(n1,n2):
        return n1 % n2
     
  2. 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. 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. 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 globally
    result = 0 #default value
    repeat = 0 #if the user decided to reuse the result of previous operation, this becomes 1
    while(True):
        #if this is the first/new operation
        if(repeat == 0):
            #number1
            num1 = input('Your first number: ')
            num1 = int(num1)
            #number2
            num2 = input('Your second number: ')
            num2 = int(num2)
        #If the user asked to use the result of the last operation in this one
        else:
            #number2
            num2 = input('Your second number: ')
            num2 = int(num2)
        #get the operator
        op = input('''Enter any of the following numbers, that correspond to the given operation:
    Just the number, not the period.
    1. Addition
    2. Subtraction
    3. Multiplication
    4. Division
    5. Modulus
    ''')
        op = int(op)
        #Call the relevant function
        if(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 result
        print('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 = result
                repeat = 1
            else:
                repeat = 0
        else:
            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.

For this project, I’m going to use another package called the time package. With this, I can give a small delay of around 300 milliseconds before the next shape is drawn so the user can see what’s going on:
  1. 1.
    Let’s import the turtle and time packages first.
    import turtle
    import time
     
  2. 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. 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 polygon
        if sides > 1:
            for x in range(0,sides):
                if(x == sides-1):
                    t.home()
                    break
                t.forward(100)
                t.right(angle)
        elif sides == 1:
            #circle
            t.circle(100,angle)
        t.end_fill()
        t.hideturtle()
        turtle.hideturtle()
     
  4. 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)
     
The images you’ll get are shown in Figure 13-1.
../images/505805_1_En_13_Chapter/505805_1_En_13_Fig1_HTML.jpg
Figure 13-1

Automated shapes

Neat! ../images/505805_1_En_13_Chapter/505805_1_En_13_Figj_HTML.gif

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.196.217