Skip to content

Commit 8d835a7

Browse files
committed
finished function arguments redo
1 parent 263ab9b commit 8d835a7

File tree

2 files changed

+62
-23
lines changed

2 files changed

+62
-23
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Die Slides zum Kurs in deutscher Sprache können unter <https://thomasweise.gith
5151
26. [Funktionen definieren und aufrufen](https://thomasweise.github.io/programmingWithPythonSlidesDE/26_funktionen_definieren_und_aufrufen.pdf)
5252
27. [Funktionen in Modulen](https://thomasweise.github.io/programmingWithPythonSlidesDE/27_funktionen_in_modulen.pdf)
5353
28. [Zwischenspiel: Unit Tests](https://thomasweise.github.io/programmingWithPythonSlidesDE/28_unit_tests.pdf)
54+
29. [Funktionsargumente](https://thomasweise.github.io/programmingWithPythonSlidesDE/29_funktionsargumente.pdf)
5455

5556

5657
### 2.3. The Slides in English

text/main/controlFlow/functions/functions.tex

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -797,44 +797,74 @@
797797
The behavior of such code could become arbitrarily hard to debug.
798798

799799
In cases where a parameter is of a mutable type and we require a default value for it, we could instead use \pythonilIdx{None}.
800-
Inside the function body, we could then check for \pythonilIdx{None} and implement appropriate behavior.
801-
802-
Back to business.\pythonIdx{function!parameter!by name}\pythonIdx{function!argument!by name}
803-
What would we do if we want to specify the value of the parameter \pythonil{sigma} of our function, but leave \pythonil{mu} at its default value?
800+
Inside the function body, we could then check for \pythonilIdx{None} and implement appropriate behavior.%
801+
%
802+
\begin{sloppypar}%
803+
Let's circle back to passing arguments to functions.
804+
Assume that we have a function \pythonil{def g(x: int, y: int)}.
805+
Normally, we would call it like~\pythonil{g(1, 2)}, in which case the function body sees \pythonil{x == 1} and \pythonil{y == 2}.
806+
However, you can also pass in arguments very much in the same way that you use to assign a variable, in the form~\pythonil{parameterName=value}.
807+
We could write \pythonil{g(x = 1, y = 2)} or, if we feel naughty, \pythonil{g(y = 2, x = 1)}.
808+
Both variants will be equivalent to our original function call.
809+
All we did is to explicitly write the names of the parameters when providing their values.%
810+
\end{sloppypar}%
811+
%
812+
\pythonIdx{function!parameter!by name}\pythonIdx{function!argument!by name}%
813+
We now revisit our \pythonil{pdf} function defined in file \programUrl{functions:normal_pdf} and used in \programUrl{functions:use_normal_pdf}, given in \cref{lst:functions:normal_pdf,lst:functions:use_normal_pdf}, respectively.
814+
The function \pythonil{pdf} has a parameter \pythonil{x} without default value, followed by a parameter \pythonil{mu} with default value, which, in turn, is followed by a parameter \pythonil{sigma} with default value.
815+
What would we do if we want to specify the value of the parameter \pythonil{sigma} of our function, but leave \pythonil{mu} at its default value?%
816+
%
817+
\begin{sloppypar}%
804818
We can do this by passing in values by parameter name:
805819
\pythonil{pdf(-2.0, sigma=3.0)}~passes in \pythonil{-2.0} for~\pythonil{x} and \pythonil{3.0} for~\pythonil{sigma}.
806-
It does not specify any value for~\pythonil{mu}, leaving it at its default value, which renders the call equivalent to~\pythonil{pdf(-2.0, 0.0, 3.0)}.
820+
It does not specify any value for~\pythonil{mu}, leaving it at its default value.
821+
This renders the call equivalent to~\pythonil{pdf(-2.0, 0.0, 3.0)}.
807822
This passing in of arguments by specifying \pythonil{parameterName=value} also allows us to specify the arguments in arbitrary order.
808823
\pythonil{pdf(mu=8.0, x=0.0, sigma=1.5)} is an example of this.
809824
Don't do such things, though.%
825+
\end{sloppypar}%
810826
%
811827
\begin{sloppypar}%
812-
\Cref{lst:functions:use_normal_pdf} provides also another interesting way to call a function in \python.
828+
\Cref{lst:functions:use_normal_pdf} illustrates also another interesting way to call a function in \python.
813829
As we have established by now, the parameters of a function have names.
814-
If we write something like \pythonil{mu=8.0, x=0.0, sigma=1.5} to assign arguments, this looks very similar to the way we created dictionary constants back in \cref{sec:dictionaries} and \cref{lst:dicts:dicts_1}.
815-
Calling \pythonil{pdf(-2.0, sigma=3.0)} is equivalent to writing~\pythonil{pdf(x=-2.0, sigma=3.0)}.%
830+
We can write something like \pythonil{pdf(mu=8.0, x=0.0, sigma=1.5)} to assign arguments.
831+
Calling \pythonil{pdf(-2.0, sigma=3.0)} is equivalent to writing~\pythonil{pdf(x=-2.0, sigma=3.0)}.
832+
Passing arguments to a function basically means to a assign values to keys~(the parameters).
833+
This is at least a little bit similar to the creation of a dictionary \pglspl{literal}.%
816834
\end{sloppypar}%
817835
%
836+
In fact, \python\ allows us to also construct the arguments for a function call in a collection.
818837
We can create a dictionary with the values \pythonil{\{"x": -2.0, "sigma": 3.0\}}.
819-
Let's call this dictionary~\pythonil{args_dict}.
820-
Can we now somehow pass in these values to~\pythonil{pdf}?
821-
We indeed can:
838+
Let's store this dictionary in variable~\pythonil{args_dict}.
839+
Can we now somehow pass in the key-value pairs from \pythonil{args_dict} as parameter-argument pairs to~\pythonil{pdf}?
840+
841+
Indeed, we can.
822842
We just have to write~\pythonil{pdf(**args_dict)}.\pythonIdx{**!function parameter}\pythonIdx{function!parameter!**}\pythonIdx{function!argument!**}\pythonIdx{function!argument!keyword}\pythonIdx{dict}
823843
Doing this will unpack the dictionary \pythonil{args_dict} and pass all the values under their assigned names in as arguments to their corresponding parameters.
824844
\pythonil{pdf(**args_dict)} is thus equivalent to~\pythonil{pdf(x=-2.0, sigma=3.0)}.
845+
825846
Two things are to notice here:
826-
First, the double~\pythonil{*}\pythonIdx{*!function parameter}\pythonIdx{function!argument!*}\pythonIdx{function!parameter!*} (called %
847+
First, the double~\pythonil{*}\pythonIdx{*!function parameter}\pythonIdx{function!argument!*}\pythonIdx{function!parameter!*}.
848+
The \pythonil{*} here is often called %
827849
wildcard\pythonIdx{wildcard}\pythonIdx{function!argument!wildcard}\pythonIdx{function!parameter!wildcard}, %
828-
star\pythonIdx{star}\pythonIdx{function!argument!star}\pythonIdx{function!parameter!star}, or %
829-
asterisk\pythonIdx{asterisk}\pythonIdx{function!argument!asterisk}\pythonIdx{function!parameter!asterisk}) %
830-
\emph{before} the dictionary, i.e., the~\pythonil{**}\pythonIdx{**!function parameter} is telling \python\ to unpack the dictionary this way.
831-
Second, default argument values still apply here, i.e., \pythonil{mu} will have value~\pythonil{0.0} in this function call.
832-
833-
Similarly, maybe we do not care about the parameter names but want pass them in by position, as we have always done in the past.
850+
star\pythonIdx{star}\pythonIdx{function!argument!star}\pythonIdx{function!parameter!star} or %
851+
asterisk\pythonIdx{asterisk}\pythonIdx{function!argument!asterisk}\pythonIdx{function!parameter!asterisk}. %
852+
The double-wildcard \pythonil{**} is written \emph{before} the dictionary.
853+
The~\pythonil{**}\pythonIdx{**!function parameter} is telling \python\ to unpack the dictionary this way.
854+
Second, default argument values still apply here.
855+
We did not specify a value for~\pythonil{mu}.
856+
This means that \pythonil{mu} will have value~\pythonil{0.0} in this function call.
857+
858+
Maybe we do not want to pass in the arguments by parameter names but simply by position.
859+
Actually, we have always done it like this in the past.
834860
Then, we can construct a sequence, e.g., a \pythonilIdx{list} or \pythonilIdx{tuple} with the parameter values.
835861
Of course, \pythonilsIdx{list} and \pythonilsIdx{tuple} do not store key-value relationships, only values at positions.
836862
We could create a tuple~\pythonil{args_tuple} with the value~\pythonil{(-2.0, 7.0, 3.0)}.
837-
Then, invoking \pythonil{pdf(*args_tuple)} will basically fill in the three values in their into the parameters, i.e., will be equivalent to~\pythonil{pdf(-2.0, 7.0, 3.0)}.
863+
864+
Then, we invoke \pythonil{pdf} like this:~\pythonil{pdf(*args_tuple)}.
865+
This will basically fill in the (three) values from the \pythonil{tuple} one by one into the parameter slots of the function.
866+
In other words, this is equivalent to writing~\pythonil{pdf(-2.0, 7.0, 3.0)}.
867+
838868
This time, only a single wildcard~\pythonil{*}\pythonIdx{*!function parameter}\pythonIdx{function!argument!*}\pythonIdx{function!parameter!*} is placed before~\pythonil{args_tuple}.
839869
We can also pass the parameters in by \inQuotes{unpacking} a list.
840870
In our example \cref{lst:functions:use_normal_pdf}, we create the list \pythonil{args_list = [2.0, 3.0]}.
@@ -845,18 +875,26 @@
845875
What do we need default parameter values for?
846876
Well, in some cases, you may want to enable a user to \inQuotes{customize} your functions.
847877
A typical example is the \href{https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html}{\pythonilIdx{plot} method} of the \pythonilIdx{Axes} object provided by popular \matplotlib\ library.
848-
You will normally provide a sequence of x-\ and y\nobreakdashes-coordinates to this function it will draw a line which goes through all the points specified this way.
878+
You will normally provide sequences of x-\ and y\nobreakdashes-coordinates to this function it will draw a line which goes through all the points specified this way.
849879
However, you can also optionally specify a color for the line, markers to be painted at the points, line dash style, a label, colors and sizes for the markers, a z\nobreakdashes-order to be used if multiple lines are drawn, and so on, and so on.
850880
The use of default arguments allows the function call to be relatively simple in most cases, while still allowing the user to do more complex formatting if need be.
851881

852882
From this example, we can also directly extrapolate a use case for building the arguments of a function in a dictionary.
853883
Imagine that you write an own function that uses one of the plotting methods of \matplotlib.
854884
Let's say that your function does a plot call where it provides ten parameter values.
855885
However, you have one special case where you need to provide one more parameter, maybe a line dash style that you otherwise do not need to provide.
856-
Then, you could have some \pythonil{if} in your code that branches to do the ten-parameter-call in one case and the eleven-parameter-call in the other.
886+
Then, you could have some \pythonil{if ... else} in your code that branches to do the ten-parameter-call in one case and the eleven-parameter-call in the other.
857887
This means that a rather complex function call appears twice in a very similar manner.
858-
If you instead construct the parameters in a dictionary and in the \pythonil{if} branch just add the eleventh parameter if need be, your code will become much simpler.%
859-
%
888+
If you instead construct a dictionary with the ten parameters.
889+
In the \pythonil{if} branch just add the eleventh parameter if need be.
890+
We now only need a single function call using the double-wildcard method.
891+
The code will become much simpler.
892+
The difference between the two cases will also be much more obvious.
893+
We have reduced the potential for errors significantly.
894+
895+
With the default parameter values and function calls via \pythonil{*} and \pythonil{**}, we learned two more aspects that make it easier for us to work with functions in \python.
896+
With the default values, we can now design more versatile function-based \pglspl{API} that allow the user of our function to provide values for some parameters, while leaving others at reasonable default settings.
897+
By constructing arguments in collections, we can create code that is easier to read when we deal with functions with many arguments that may be called slightly differently depending on the situation.%
860898
\FloatBarrier%
861899
\endhsection%
862900
%

0 commit comments

Comments
 (0)