Understanding Functions In Python-trickcode

Python function, variables, collections, and loops,Docstrings,keyword arguments,keyword arguments,Optional parameters,Return values,Calling functions,Defining a function
Share it:



Python function

Now we have learned the basics of Python programming: variables, collections, and loops. If you have followed the examples and the tutorial you might feel that sometimes we use too much code and it can be leveraged a bit. But maybe you do not know how to do it.

Most of the time the solution is to introduce functions. We have encountered functions of other modules that we used just like isupper() of strings or choice() of the random module.

If we have learned mathematics then you know about functions already. Mathematicians can do very nasty things with them but programmers too. The aim of a function is to produce a result which is determined only by the parameters passed to the function.

In the programming language, we can look at a function as a black box where we send in a defined number of parameters (0 and more) and the function returns a result. This means if you know another programming language such as C++ or Java then you know about void functions.


Defining a function 

A function is created with the def statement. The general syntax looks like this:

def function_name(parameter list):
function_body of statements

The parameter list contains zero or more elements. If you call a function then you say arguments instead of parameters but this is terminology, in my eyes, it is ok if you just say parameters even if you call a function. These parameters are mandatory if you do not declare them optional. We will take a look at optional parameters in the next section.

Every time a function is called the statements in its body are executed. Naturally, you can use the pass statement in the function’s body to do nothing — but in this case, the pass statement is executed too.

As you might know: a function has to have at least one statement in its body. Without it you get an error:


>>> def no_body_function():
...
File "<stdin>", line 2
Well, this error message is not the most speaking but in this case, the compiler is missing an indented block — at least one statement for the function’s body.

So let’s write a simple function which is an exchange calculator. It gets two parameters: the value and the exchange rate and it returns the changed value (value multiplied by exchange rate).



def exchange(value, rate):
return value*rate


So every time you define a function make sure you have an indented body. In this article, the interactive interpreter of Python the definition would look like this.



>>> def exchange(value, rate):
...     return value*rate
...

And as I mentioned previously you can have functioned without return statements too. However most of the time you won’t use such functions but for the sake of brevity let’s see an example here too:


>>> def no_return():
...     print("This function has no return statement")
...

Calling functions



I think this is easy. You already know how to call functions but let’s quickly go through it. If you have a function definition then you can call it with passing the right arguments as parameters and you are good to go.

And as I told you before we already called functions. They have the very first and basic function we called was print(). You can call it without any parameters and in this case, the prints a new-line character to the output (an empty line). Alternatively, we can pass an arbitrary number of parameters, each separated with a comma (,) and they will be printed to the output too.



Now let’s call the two functions we defined in the previous section.


>>> no_return()
This function has no return statement
>>> exchange(123, 1.12)
137.76000000000002

As you can see there is nothing complex in calling functions.


Return values


Previously I said that functions return values — even if you do not explicitly write a return statement. Now it is time to verify my statement so I will show you that even the no_return() function returns a value, and this value is None.

To see the return statement of the function let’s simply wrap the function call into a print() function call.


2
3
4
5
>>> print(no_return())
This function has no return statement
None
>>> print(exchange(123,1.12))
137.76000000000002


Here you can see that even a function without return statements returns a None. This means in such cases you have to be careful how you use the return value because with a None you can do almost nothing just use it in a boolean expression — with the care of course.



As you can see in the example above you can use None in mathematical operations for example and None is not False.

To fix the second part of the example we could change the code like this:


>>> if not result_value:
...     print("Nothing useful...")
... else:
...     print("Wow, we have got True back!")
...
Nothing useful...

The same goes for using only return without any value. It results in the same None after returning than no return statement at all. Why should be this good? For example, you want to terminate your function if a condition evaluates to true and want to return nothing. Naturally, you can use return None but the more pythonic solution would be to simply use return.

Optional parameters

You can create functions with optional parameters. This means that these parameters do not have to be passed to the function. In this case, their default value is used — and sometimes a block of statements is skipped if the optional parameter gets its default value.

Optional parameters have to follow the mandatory parameters and they have to have a default value. This value is used when you call the function and you do not provide this argument.

As an example let’s take the previously introduces exchange function. As a quick reminder here is the definition:

If we try to call this exchange function with only 1 parameter (with the value) then we get an error from the interpreter:
Now let’s make the rate variable optional and set it’s the default value to 1 to be able to call this function for the same currency without any exchange.

So the solution is to have a default value for the rate parameter in the function and set this value to 1.

To see how this works I changed the code a bit to display the current exchange rate too:

Now the rate parameter is optional, we can call this function with or without a rate:
Ordering of the optional and required parameters do matter. For example, if we change the order and add rate=1 as the first argument before value we will get an error:
If you think about it you will get the idea why it is this way: what if we provide one argument. Would it be the optional one or the required one? Well, the interpreter could not tell and maybe you would end up with the wrong result.

Keyword arguments

It can happen that you will encounter the term “keyword arguments” when learning Python. They are in fact the same as optional arguments: they have a name and a default value. And this name is the keyword and you can use it to assign a new value to this parameter.

Let’s look at the previous example again: rate is the keyword argument of the function. Because exchange has only one optional argument you can call it in two flavors with both parameters:


The second case is where we use keyword arguments.

Now let’s take another example where we have multiple optional parameters so you see how it really works with keyword arguments.

The example will be very basic: we define a function that takes four parameters a, b, c, d, and executes the following calculation: a + b – c + d. And to have it work it requires only 2 parameters, two are optional.

Now we can optionally pass values for the variables c and d. If we already know that providing a value for c has two flavors.
As you can see, you do not have to provide all the values, it is enough to assign the value for d when calling the function. This is why they are called “keyword arguments”. And you might get the idea: there are functions which have a lot of arguments and most of the time you only need their default values. So you do not pass them along (so you do not have to know what the default value is) and you can fine-tune the function call with a single parameter which is somewhere in the list by using its keyword.

Taking this concept a bit further we can call functions with this keyword syntax in a way you cannot imagine in other languages: you are free to order the values as you want until you provide all the required arguments with their names.


As you can see you cannot omit the names of required arguments if you mess around with the order. In this case, it is required to have them named to let the interpreter know that you want to set those values.

Traps with keyword arguments

Above we have seen one way of using keyword arguments. However, every coin has two sides. Let’s dig a bit deeper when those default values are assigned. It is done when the function is created (so when the interpreter parses the function definition) and not when the function is invoked. This means we do not see any difference as long we use immutable types for named parameters/keyword arguments.

However, problems can arise when we use mutable variables, for example, a list:

In the example above we append the parameter s to the parameter lst if the length of s is at most 3. This seems fine if we pass both parameters to the function. But let’s call this function some times…


As you can see this results in unexpected behavior. We pass in one string and get back a list with more elements than expected.
However, this is not the full truth. We can make things even worse:


In the example above we have added an element to the list which is clearly longer than 3 characters — which again can lead to unexpected behavior.

To fix this let’s change the function definition:



Docstrings

Sometimes (I hope every time) you will feel the urge to document your functions. This you can do with simple comments put around the function definition.

However, there is a common practice which you should follow: docstrings. These are simple documentation strings placed right after the function definition. They have the special three quotation format because they are multiline strings describing your function.

Sometimes documentation is longer than the function itself. A convention is to make the first line of the docstring a brief one-line description, then have a blank line followed by a full description, and then some examples as they would appear if typed in the interactive interpreter.

So let’s use this guidance and add documentation to our append_if_short function.


This is any string, lst is an optional list-type parameter. If lst is not provided a new lst gets a new empty list assigned. If len(s) < 4 then s is appended to lst and lst is returned.
Share it:

python

Post A Comment:

0 comments: