So far in Python, we've been using several different functions that are built-in parts of the Python language. An example of a built-in or standard Python function that we've been using quite a bit is the print() function. The print() function takes whatever object you pass it between the parenthesis, and prints it to the Python console as output, like this:
print("Hello!")
This outputs:
Hello!
It seems simple, but the print() function actually does a number of things, including starting a new line, deciding how to print whatever it is you. give it depending on the type of thing it is, and so on. The point is, Python functions are simple commands that sometimes actually do very complex things.
Python version 3.11.4 has 68 built-in functions, which might sound like a lot at first. However, it doesn't take very long for most budding programmers to realize that they want to do more than the basic things that Python offers. We also often have a good reason to package complex actions into a single command, so that they can be executed over and over without repeating all of the steps.
This is where custom functions come in very handy.
Here are some of the benefits of using custom functions:
Let's say, somewhere in some program I want to write, I'd like it to print out the following Haiku about Python:
Python, the language
Of simplicity and power
A joy to program in
We might print out those three lines using three print statements, like this:
print("Python, the language")
print("Of simplicity and power")
print("A joy to program in")
This would be fine, if we only wanted to print it out one time. But if the Haiku needed to appear several times throughout the code, it could lead to a lot of wasted effort, redundant coding, and possibly even increased errors in the program. It would be a much easier, cleaner solution if we turned the Haiku into a custom function, like this:
def writeHaiku():
print("Python, the language")
print("Of simplicity and power")
print("A joy to program in")
Now, each time we called the function writeHaiku(), it would reliably spit out those same three lines. That might not seem like a big deal yet, but this is just the very tip of the iceberg when it comes to custom functions.
Let's take apart the writeHaiku() function, and get a feel for the important parts of a function:
To call a function is to execute the code inside the function's definition. Calling a function is easy, especially if the function doesn't require any parameters. All you do is type the name of the function, including the parenthesis after the name, like this:
writeHaiku()
The result of this would be the following:
Python, the language
Of simplicity and power
A joy to program in
Parameters allow us to create even more powerful functions, by allowing us to provide a function with additional information that it can use, right at the time when the function is called.
Take a look at the following code as an example:
def sayHello (strName):
print("Hello, " + strName)
sayHello("Bill")
Let's take each piece of the code above, and see how it all works together:
That part of the code was the definition of the function. In the next line we call the function by using the name of the function and providing it with what is called an argument. An argument is the data that we provide to a parameter of the function. In this case, the string that we send as the argument is “Bill”, which then gets concatenated (this is the word we use when adding two or more strings together) with the other string and printed out, resulting in the output:
Hello, Bill
Here is a slightly more complicated function that has two parameters, and also includes comments explaining each line:
# Define the addNumbers function
def addNumbers(intNum1, intNum2):
# Create a variable intAnswer, and set it to the value of intNum1 plus intNum2
intAnswer = intNum1 + intNum2
# Use an f-string to print out the values of the variables in a sentence.
print(f"The sum of {intNum1} and {intNum2} is {intAnswer}.")
# Call the function, using 5 and 7 as the arguments.
addNumbers(5, 7)
You can see in the code above that the function, called addNumbers, takes two parameters: intNum1 and intNum2.
The function is then called using the arguments 5 and 7.
Inside the function, the parameters behave like variables of the same name, so intNum1 equals 5, and intNum2 equals 7.
The result of this code, when it is run, is:
The sum of 5 and 7 is 12.
So far, we've been looking at custom functions that do something. Namely, we've been making functions that print something out when called, whether they are functions that require arguments or not.
There are two big categories of functions, and sometimes a function can be in both categories:
When a function returns something, that means that whatever the function does, it produces some kind of result that gets sent back to the program. That result can be fed into another function, set as the value of a variable, or printed out. If a function that returns something is called, but nothing is done with what it returns, then nothing will happen in the console.
Take the following code for example:
# Define a function that says "Hi Bill!"
def sayHiBill():
# Create a string for the message
strHiBill = "Hi Bill!"
# Send the message back to Python
return strHiBill
This code creates a very simple function. However, notice that instead of printing something out, it just returns a message in the form of a string. So, let's call this function, like this:
sayHiBill()
Nothing appears to happen. However, something actually did happen - you just didn't see the result because we didn't tell Python to do anything that would be visible to a user. We call the sayHiBill function, which returns a message. However, since we don't tell Python what to do with the message, it just goes away.
If we call the same function, and assign the return value to a variable, then we can print it out, like this:
# Set strMessage to the value of what is returned by the sayHiBill() function.
strMessage = sayHiBill()
# Print out the value of strMessage
print(strMessage)
With this change to the code, now we will see the message printed to the console.
However, if that's all we want to do, then we can just put the function right inside of the print function, like this:
print(sayHiBill())
This will do the exact same thing, but with less work. Yay!
I want to make sure that you notice the parenthesis in the code above. Every function always has its own set of parenthesis when it is called. If no arguments are required, then they are empty, but they are still there.
As we learned in the section above, most functions either do something or return something, but it is completely possible to do both.
Check out the following code, which also takes two parameters:
# Define a custom function called addNumbers, with two parameters.
def addNumbers(intNum1, intNum2):
# DO something - Print a message that we are adding the numbers
print(f"Now adding {intNum1} and {intNum2}...")
# RETURN something - Send back the sum of the two numbers given.
return intNum1 + intNum2
# Call the function addNumbers with 3 and 4 as the arguments.
intResult = addNumbers(3, 4)
# Use an f string to print out the result in a nice sentence.
print(f"The answer is {intResult}.")
In the code above, the function prints out a message to the console that the numbers are being added, using an f-string to insert the numbers into the sentence from the arguments given for intNum1 and intNum2. Then, the function returns the sum of the two numbers.
The function is called using the assignment operator (=) to set the value of the intResult variable to the return value of the function. Finally, the result is printed into a sentence using another f-string.
Here is the result.
Now adding 3 and 4...
The answer is 7.
So there you have it. A function that both does something and returns something.
You might be asking yourself – Couldn't you just have had the function print both lines? Or, could we have just had the function just return the answer and do the printing outside the function. The answer is “yes” to both questions, and that's actually a good thing. While this flexibility might be a little confusing at first, it also gives you a lot of power to create the kind of programs you want, in a way that makes sense to you.
Programming is actually a very creative activity – it just isn't often thought of that way.
In an earlier section, we learned that if a function has a parameter in the definition, then we are always required to give an argument to the function when we call it. However, this isn't always true. If we want to, we can make parameters optional when we define the function.
Here is a very simple example of what that would look like:
# Define a function called sayHi, with one optional parameter.
def sayHi(strName="Bill"):
# Print a greeting using an f-string to insert the value of the parameter.
print(f"Hello, {strName}!")
# Call the function with no argument.
sayHi()
# Call the function again, but with "George" as the argument.
sayHi("George")
In the code above, we define a function called sayHi. In the definition, we specify a parameter called strName, but there's something special about it. When we specify the strName parameter, we also give it a default value of “Bill”, which means that if someone gives a value when they call sayHi, then it will use the given value, but if they do not, then it will use the default value of “Bill”.
This makes the parameter optional.
Here is what we get when we run the code:
Hello, Bill!
Hello, George!
We can also have more than one optional parameter. Check this out:
# Define the function sayIntro with optional parameters strName and intAge
def sayIntro(strName = "Bill", intAge = 47):
# Print a sentence, inserting the values of the parameters using an f-string.
print(f"My name is {strName}, and I am {intAge} years old.")
# Call the function with no arguments
sayIntro()
# Call the function with two arguments.
sayIntro("George", 25)
# Call the function with one argument, unnamed.
sayIntro("Sam")
# Call the function using a named argument to specify the intAge parameter.
sayIntro(intAge=25)
In this scenario, we have two parameters in the function definition, strName and intAge. Both have default values, meaning both are optional, independent of each other. This gives us a lot of options when it comes to calling the function. Here is the result when the above code is run. See how the different ways of calling the function work to produce the output for each line?
My name is Bill, and I am 47 years old.
My name is George, and I am 25 years old.
My name is Sam, and I am 47 years old.
My name is Bill, and I am 25 years old.
Optional parameters give us a lot of power and flexibility. Generally speaking, it is better to put required parameters (ones with no default) first in the definition, and then the optional parameters last. However, you can have a mix of both types if you want to.
No terms have been published for this module.
Test your knowledge of this module by choosing options below. You can keep trying until you get the right answer.
Skip to the Next QuestionFunctions in Python are a very powerful thing. They allow us to create reusable blocks of code that can simplify our programs and save us from overly long or redundant code. To explore the idea, we will create a program that fills the screen with snowflakes of different sizes and colors until we stop it. Snowflakes are a great way to study this, because a snowflake is made up of different “arms” that all look the same. By designing one arm, and then repeating that same code multiple times, we will end up with a snowflake.
I’ll give you some code to start with, and then help you make some modifications to it. Finally, you’ll get creative by making some snowflakes of your own.
First, check out the following code:
def makeArm():
turtle.forward(30*intScale)
turtle.right(90)
turtle.forward(2*intScale)
turtle.right(90)
turtle.forward(30*intScale)
This is a custom function. It starts out with the “def” keyword, which means “define”. Next, the name of the function (in this case, makeArm). Then parenthesis, which will stay empty for now, followed by a colon. This is the start of our function code. The function code block continues on the next line, which will be indented. The function continues for the reminder of the indented lines until the next line that is not indented at the same level.
To use the function, or “call” the function as we say, we simply use the name of the function with the parenthesis, and without the “def” or the colon. When we call a function, all of the code in the function’s block is run.
If you were to run the above code one time, it would draw a rectangle. The size of the rectangle would depend on the size of the number in the intScale variable. Try playing around with it by running the following code:
# updated code
import turtle
myturtle = turtle.Turtle()
def makeArm(intScale):
myturtle.forward(30*intScale)
myturtle.right(90)
myturtle.forward(2*intScale)
myturtle.right(90)
myturtle.forward(30*intScale)
makeArm(10)
screen = turtle.Screen()
screen.exitonclick()
Run this code, then change intScale to 10 and run it again. The makeArm function makes a piece of our snowflake. If we run it multiple times, and change the angle a little bit each time, then it will draw a snowflake shape.
The following code uses the makeArm function to draw snowflakes of random colors and sizes all over the screen. Try it out by copying and pasting into PyCharm:
# updated code
import random
import turtle
myturtle = turtle.Turtle()
screen = turtle.Screen()
arColors = ["deepskyblue", "skyblue", "lightblue", "powderblue", "lightsteelblue"]
xpixels = screen.window_width()//2
ypixels = screen.window_height()//2
myturtle.speed(0)
def makeArm(intScale):
myturtle.forward(30*intScale)
myturtle.right(90)
myturtle.forward(2*intScale)
myturtle.right(90)
myturtle.forward(30*intScale)
while True:
xColor = random.choice(arColors)
myturtle.pencolor(xColor)
myturtle.fillcolor(xColor)
myturtle.penup()
xloc = random.randint(-1*xpixels,xpixels)
yloc = random.randint(-1*ypixels,ypixels)
myturtle.goto(xloc,yloc)
myturtle.pendown()
intScale2 = random.randint(1,10)/5
myturtle.begin_fill()
for x in range(9):
myturtle.left(140)
makeArm(intScale2)
myturtle.end_fill()
You may not know for sure what all of this code does, but that’s ok.
What I want you to do is play around with it, a little at a time, and see what happens. Try to make your own snowflake shapes and even colors if you want,
For A6, we will be making a game of Rock, Paper, Scissors using functions. Please take the time to think through the UI and the User Experience -- make it easy to play/use, and provide good prompts and explanations when needed.
Here are the sample functions we went over in the class video:
def userGuess():
while (True):
strGuess = input("(r)ock, (p)aper, or (s)cissors? ").strip().lower()
if (strGuess == "r" or strGuess == "rock"):
strReturn = "r"
print("You chose rock.")
break
elif (strGuess == "p" or strGuess == "paper"):
strReturn = "p"
print("You chose paper.")
break
elif (strGuess == "s" or strGuess == "scissors"):
strReturn = "s"
print("You chose scissors.")
break
else:
print("That isn't a valid response. Try again.\n")
return strReturn
def compGuess():
arChoices = ["r", "p", "s"]
strReturn = random.choice(arChoices)
if (strReturn == "r"):
print("The computer chose rock.")
elif (strReturn == "p"):
print("The computer chose paper.")
else:
print("The computer chose scissors.")
return strReturn
def whoWon(strU, strC):
if (strC == strU):
print("It's a tie.\n")
return "t"
else:
if (strU == "r"):
if (strC == "p"):
print("Computer wins!\n")
return "c"
else:
# C chose scissors
print("You won!\n")
return "u"
elif (strU == "p"):
if (strC == "r"):
print("You won!\n")
return "u"
else:
# C chose scissors
print("Computer wins!\n")
return "c"
else:
# User chose S
if (strC == "r"):
print("Computer wins!\n")
return "c"
else:
# C chose paper
print("You won!\n")
return "u"