def greeting(name):
if name == 'Batman':
return 'Hello Batman! So, nice to meet you!'
else:
return f'Hello {name}!'
Functions (Need)
What to Expect in thie Chapter
By now, you will be comfortable using functions. In addition, I hope you are satisfied with the idea that a function is just a chunk of code that does a specific conceptual task. In this chapter, I will show you how to craft your own functions. In addition to its practicality, the modularity of functions prompts us to think of solutions about modular solutions to problems.
User defined functions
print()
is an example of an internal function in Python. You can also create your own functions. There are two ways to do this: named and anonymous.
Named functions that return
We define the function by:
and use it as:
"Super Man") greeting(
or
="Super Man") greeting(name
The function’s name is greeting
and it accepts a single argument called name
.
Notice the keyword def
, the colon (:
) and the indentation that demarcates the function’s code block. Notice also that I have used the keyword return
to get an output from the function. When Python sees a return
keyword it jumps out of the function with the return value. You can pick up the returned value by assigning it to a variable or even use it directly like:
=greeting(name='Super Man')
greetprint(greet)
or this works too:
print(greeting(name='Super Man'))
Incidentally, you can use return
only within a function.
I also like to point out that you can return most anything! Here is an example of a function that accepts a list and returns the maximum, minimum and mean.
def basic_stats(numbers):
=np.array(numbers)
np_numbersreturn np_numbers.min(), np_numbers.max(), np_numbers.mean()
Here is how you can use it:
= basic_stats([1, 2, 3, 4, 5]) list_min, list_max, list_mean
Named functions that don’t return
A function does not have to return anything. A good example is print()
, which does something but does not return a value. You will often need functions like these, for instance, to save data to a file. I will show you a few of such functions in the later chapters.
Anonymous functions
Anonymous or lambda functions are suitable for short one-liners. The following examples accept a single argument called name
.
= lambda name: f"Hello {name}!" my_short_function
We can use it like
="Super Man") my_short_function(name
A lambda
function always returns the value of the last statement.
The above example is not a very good ‘anonymous’ one because I have used a name! So let me show you another one where things are really anonymous.
Let’s say I want to sort a 2D list. I can use sorted()
function for this as follows:
=[[9, 0, 10],
numbers8, 1, 11],
[7, 2, 12],
[6, 3, 13],
[5, 4, 14],
[4, 5, 15],
[3, 6, 16],
[2, 7, 17],
[1, 8, 18],
[0, 9, 19]]
[
sorted(numbers) # Sort by comparing the default key
# (i.e. the 1st element)
[[0, 9, 19], [1, 8, 18], [2, 7, 17], [3, 6, 16], [4, 5, 15], [5, 4, 14], [6, 3, 13], [7, 2, 12], [8, 1, 11], [9, 0, 10]]
Notice that this sorting is based on comparing the first elements of the sub-lists. If I want to use some other criteria, then I need to specify a key
that can be used for comparison. I can use a lambda
function for this as follows.
sorted(numbers, key=lambda x: x[1]) # Sort by comparing a custom key
# that uses the 2nd element
[[9, 0, 10], [8, 1, 11], [7, 2, 12], [6, 3, 13], [5, 4, 14], [4, 5, 15], [3, 6, 16], [2, 7, 17], [1, 8, 18], [0, 9, 19]]
This is really powerful! I can specify almost any criterion I like. For example, I can ask them to be sorted according to the sum of the elements of the sub-lists.
sorted(numbers, key=lambda x: sum(x)) # Sort by comparing a custom key
# that uses the sum of the elements
[[9, 0, 10], [8, 1, 11], [7, 2, 12], [6, 3, 13], [5, 4, 14], [4, 5, 15], [3, 6, 16], [2, 7, 17], [1, 8, 18], [0, 9, 19]]
Optional arguments
Python allows us to make arguments to our function optional. To do this, we need to give the argument a default value so that it always has something to work with.
def greeting(name='no one'):
if name == 'Batman':
return 'Hello Batman! So, nice to meet you!'
else:
return f'Hello {name}!'
Now we can run this function without an argument, and it will still work without throwing an error.
greeting()
'Hello no one!'
For another example, let’s look at the documentation for print()
.
?print
Docstring:
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
Type: builtin_function_or_method
You see that print()
can accept other arguments and are optional with default values. However, we can specify them if we like; here goes.
print('I', 'am', 'Batman!') # Just for comparison
## I am Batman!
print('I', 'am', 'Batman!', sep='---')
## I---am---Batman!
The importance of functions?
An argument for functions
Now that you know a bit about creating functions, let me highlight why functions are a good idea.
Abstraction of details The most important benefit of functions goes beyond programming and relates to your ability to strategise. If you break up a complicated solution into modular chunks (i.e. functions), it becomes easier to think about it because you are not dealing with all the details all at once. As a result, it is easier to focus on your overall solution because you are not distracted by unnecessary information. This hiding of ‘stuff’ is called abstraction.
The concept of abstraction can be tricky to grasp. So, let me share an analogy related to driving. A vehicle has many abstracted systems, amongst which the engine is a good example. You do not need to know the engine’s details (e.g. electric, petrol, diesel, guineapig) to use it. You can use the engine of almost any car because you are not required to know what happens inside. This frees up your resource because you are not distracted by unnecessary details. Of course, there will be times when you want to know how an engine works to pick the best engine, but this is not all the time.
Reusability of code If you encapsulate a chunk of code in a function, it becomes straightforward to reuse instead of copying and pasting at different places. This means your code will be shorter and more compact.
Maintainability of code With functions, your code is easier to change and maintain because you need only make changes in one place, at the function definition.
A word of caution
I have seen instances where functions are abused; for example, by trying to do too much or having too many arguments. They can also be overused. Having too many functions can make it difficult to read your code and also increase computational overheads. You will get a better feel for when to use functions with experience, but please bear in mind that functions can be misused.