Finding Magic in Python
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 115 | |
Author | ||
Contributors | ||
License | CC Attribution - NonCommercial - ShareAlike 4.0 International: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/58746 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
Gamma functionGoogolACIDTupleReal numberSocial classWordFunctional (mathematics)outputInstance (computer science)Sheaf (mathematics)Canadian Light SourceAttribute grammarMultiplication signComputer-assisted translationDifferent (Kate Ryan album)CASE <Informatik>CodeProjective planeObject (grammar)TheoryDefault (computer science)Software developerNumberMereologyVirtual machineWrapper (data mining)Constructor (object-oriented programming)Type theoryData dictionaryPresentation of a groupSlide ruleMathematical optimizationLogicProcess (computing)Chemical equationPoint (geometry)Fluid staticsGroup actionKey (cryptography)Function (mathematics)Parameter (computer programming)BitTerm (mathematics)Flow separationFactory (trading post)Letterpress printingStatement (computer science)Cartesian coordinate systemModule (mathematics)Degree (graph theory)Sound effectCasting (performing arts)ResultantImplementationSign (mathematics)1 (number)String (computer science)Data storage deviceSoftware testingMathematicsElectronic mailing listGradientPower (physics)Maxima and minimaStudent's t-testState of matterArc (geometry)Graphics tabletQuarkVariable (mathematics)Revision controlBoolean algebraMetropolitan area networkLevel (video gaming)Inheritance (object-oriented programming)Object-oriented programmingExtension (kinesiology)Moment (mathematics)Message passingCodeFree variables and bound variablesLambda calculusError messageLine (geometry)2 (number)InformationElementary arithmeticField (computer science)FreewareWeb pageNumbering schemeFaculty (division)Repository (publishing)Basis <Mathematik>AlgorithmTypprüfungRepresentation (politics)SurfaceBounded variationCarry (arithmetic)Price indexData structureUniverse (mathematics)AbstractionHierarchyPlanningSemantics (computer science)Exception handlingBlogTheory of relativityBookmark (World Wide Web)Modal logicSummierbarkeitProgramming paradigmLoop (music)Category of beingCorrespondence (mathematics)Complex (psychology)IntegerSubject indexingInformation engineeringFamilyMachine learningComputer programmingSinc function12 (number)Position operatorSemiconductor memoryHookingMeeting/Interview
00:40
Web pageFaculty (division)ArmObject (grammar)Attribute grammarData structureLoop (music)Social classWordInheritance (object-oriented programming)Function (mathematics)Projective planeFreewareSocial classVirtual machineReal numberRepository (publishing)Instance (computer science)CodeAlgorithmMereologyCodeBasis <Mathematik>Inheritance (object-oriented programming)Message passingPresentation of a groupRight angleAttribute grammarFree variables and bound variablesObject (grammar)Parameter (computer programming)Line (geometry)Point (geometry)Resultant2 (number)WordInformation engineeringInformationMachine learningObject-oriented programmingUniverse (mathematics)Function (mathematics)Functional (mathematics)Web pageFaculty (division)Bookmark (World Wide Web)String (computer science)Student's t-testFamilyData structureComputer programmingComputer animation
09:25
System programmingInheritance (object-oriented programming)TheoryComputer-assisted translationLoop (music)ImplementationSocial classType theoryoutputParameter (computer programming)WordPoint (geometry)Constructor (object-oriented programming)Internet service providerIndependence (probability theory)Mountain passGradientLetterpress printingSoftware developerFluid staticsSoftware developerFluid staticsSocial classLevel (video gaming)Parameter (computer programming)outputGradientStudent's t-testType theoryNumbering schemeCodeInstance (computer science)Different (Kate Ryan album)Object (grammar)Inheritance (object-oriented programming)Attribute grammarObject-oriented programmingCartesian coordinate systemConstructor (object-oriented programming)1 (number)Process (computing)Sheaf (mathematics)MathematicsModal logicUniverse (mathematics)Programming paradigmState of matterCategory of beingString (computer science)Complex (psychology)Variable (mathematics)Functional (mathematics)BitNormal (geometry)Elementary arithmeticComputer animation
18:10
Universe (mathematics)Task (computing)Data dictionaryParameter (computer programming)Function (mathematics)Power (physics)Internet service providerCASE <Informatik>Letterpress printingRegular graphIdentical particlesKey (cryptography)outputDefault (computer science)Key (cryptography)Factory (trading post)Electronic mailing listRegular graphType theoryData dictionaryBoolean algebraVariable (mathematics)Constructor (object-oriented programming)Object (grammar)Parameter (computer programming)outputLambda calculusSocial classFunctional (mathematics)Flow separationCASE <Informatik>Attribute grammarComputer-assisted translationMultiplication signNumberPower (physics)MereologyCountingLoop (music)SummierbarkeitSlide ruleConfidence intervalGroup actionFunction (mathematics)Instance (computer science)BitMetropolitan area networkComputer animation
26:54
Function (mathematics)outputStatement (computer science)Wrapper (data mining)WordProcess (computing)CodeSurfaceInheritance (object-oriented programming)Universe (mathematics)AbstractionHierarchyImplementationCategory of beingObject (grammar)WordString (computer science)Different (Kate Ryan album)MathematicsCartesian coordinate systemoutputCodeFunctional (mathematics)Module (mathematics)Arc (geometry)FlagParameter (computer programming)ImplementationFunction (mathematics)Revision controlQuarkCasting (performing arts)Letterpress printingVariable (mathematics)Statement (computer science)Software testing1 (number)Type theorySemiconductor memorySurfaceSound effectCASE <Informatik>Inheritance (object-oriented programming)Social classHierarchyFluid staticsFlow separationAbstractionWrapper (data mining)HookingMultiplication signMereologySheaf (mathematics)Point (geometry)ResultantRight angleData storage deviceWritingMultiplicationComputer animation
35:39
Inheritance (object-oriented programming)Letterpress printingAbstractionObject (grammar)ImplementationNormal (geometry)Social classCategory of beingQuadratic equationData structureTupleAttribute grammarBounded variationField (computer science)CodeUniverse (mathematics)ArmCanadian Light SourceExtension (kinesiology)Keyboard shortcutException handlingSocial classTupleKeyboard shortcutBounded variationExtension (kinesiology)Maxima and minimaMultiplication signField (computer science)Student's t-testSheaf (mathematics)Type theoryIntegerSubject indexingImplementationCasting (performing arts)Error messageCodePrice indexSlide rulePosition operatorInheritance (object-oriented programming)Data structureRight angleObject (grammar)Message passingSign (mathematics)Representation (politics)AbstractionGroup actionStatement (computer science)MathematicsAttribute grammarInstance (computer science)Universe (mathematics)Repository (publishing)BlogCorrespondence (mathematics)TypprüfungCartesian coordinate systemComputer-assisted translationComputer animation
44:23
World Wide Web ConsortiumSinc functionMoment (mathematics)MathematicsMultiplication signCodeGradientStudent's t-test12 (number)Different (Kate Ryan album)Lecture/ConferenceXMLMeeting/Interview
Transcript: English(auto-generated)
00:05
All right, we're back again with Anna-Lina, Anna-Lina, I'm sorry, who is going to talk about finding magic in Python. She enjoys using Python for her personal projects and professionally. She has worked as an AI resident at
00:20
Microsoft Research and is currently working as a machine learning engineer in OX in Germany. Where in Germany are you streaming from? I'm from Bonn, that's close to Cologne. I guess that's what most people know. Okay. Over to you, Anna-Lina. Yes, thanks a lot. As you mentioned already, my name is Anna-Lina,
00:41
and I'm really excited to be here today, and I want to use the next 45 minutes to take you on a magical journey through the world of Python. I hope that you will enjoy it as much as I did when preparing this presentation. Just a few words about myself, I'm working as a machine learning engineer in a German company called InnoVEX,
01:01
where I work on various projects surrounding data engineering and machine learning. In my free time, I'm working in a voluntary project called Ka-e-marchule. Ka-e is German for AI, where we teach kids in German schools about AI and machine learning. I like working on personal projects and usually share
01:23
those with the community either on GitHub or my personal webpage. The two most popular repositories you might find interesting are Machine Learning Basics, which implements fundamental machine learning algorithms in plain Python, and then there's the Magical Universe, which is the basis of today's talk.
01:42
I started the Magical Universe a few years ago, when I decided to participate in the 100 days of code challenge. For those of you who don't know the challenge, it's about spending some time, even if it's only five minutes a day, and writing some part of code.
02:01
I wanted to look into some of the Python concepts I've been using for a while, but also some new ones. Because I absolutely love Harry Potter, I decided to work through the concepts using my own Magical Universe. This really turned the coding challenge into a lot of fun. Let's jump right into it.
02:22
In my opinion, every good talks needs a story. Today's presentation is based on a Magical Universe I created called The Tales of Castle Kilmer, and I want to present the main story and characters to you, such that we can work with them throughout this presentation. And then the goal of the presentation would be to
02:41
create the world of Castle Kilmer using Python. The main character of our universe is called Lizzie Spinster, and she's a quiet, clumsy girl of age 12, who loves to read and is therefore sticking her nose into books most of the time. Her best friend, called Luke Berry, is living next door and has a completely different personality.
03:03
So he's usually full of energy, full of mischief, and is constantly trying to convince Lizzie to play tricks on other people. One day, Lizzie's parents decide to send her to Castle Kilmer, a well-known magical boarding school, with the hope that she will become more open-minded when being surrounded by many other children.
03:22
But only after Luke's parents allow him to go to Lizzie agrees. So Castle Kilmer is a really old school, which has been around for centuries. No one really knows how old it is, but it is very well-known all around the world. The headmistress of Castle Kilmer is called Miranda Mirren.
03:42
Although she's a very strict and stiff witch, she cares greatly about extracurricular activities. And her favorite is the Club of City Walkers, which she has presided over since she joined the school. Castle Kilmer is divided into different faculties. Each faculty is focused on a certain subject
04:01
and is supervised by a professor. And naturally all students have to take certain mandatory courses like spellcasting, but they are also free to choose courses from other faculties. And on their first day of school, Lizzie and Luke quickly learned that actually not all kids at school are nice, but some kids and their families have been associated
04:23
with an evil magical society called the Dark Army, where the Dark Army is led by a particularly dark wizard called Master Odon. Not many people who know how he looks like, but everyone knows his name because he has been pulling the strings
04:40
behind the wheelings and dealings of the Dark Army for years. Yeah, so this gives us the main information we need for the presentation. There's lots more to discover in the project, but this will get us started. So we will start out with some simple Python features and then progressing to more advanced concepts in the end.
05:01
To get started with the universe, we have to talk about classes first. Using classes in coding is tightly coupled to the concept of object-oriented programming. In this concept, programs are designed by creating objects that interact with each other and where each object can contain attributes and methods.
05:23
Object-oriented programming can be used to represent the structure of the real world. If you think about it, we have lots of classes actually in the real world and instances of these classes. For example, there would be the class person and then individual people like you and me who are instances of this person class.
05:43
And so what is a class? Precisely, a class acts as a blueprint for an object. It describes how objects, so-called members of the class are structured and which attributes and methods they have. The syntax for creating an empty class is quite simple.
06:02
So we start our universe with the class CastleKilmerMember. At the moment, the class does not contain any code. So we use the keyword pass as a placeholder in the body of the class. And yeah, if you don't know pass, pass can just be used to denote places where we will eventually put code.
06:22
Right now, it allows us just to run this class without getting an error. Now, if we want to create an actual object and so-called instance of the class, we have to instantiate the class. And this is also very simple as we can see here in the second line of code. And we just call the class and assign the result to a variable called KilmerMember.
06:43
Right now, this class is quite boring. It's not very useful. And we want to add some attributes and methods to make it more interesting. So each CastleKilmerMember will have a name, a birth year, and a sex. So we know whether the member is male or female. And this information is included
07:02
in the so-called Dunder-Innit Method. If you don't know what the word Dunder, it stands for double underscore and is typically used when talking about methods that start and end with two underscores. So this Dunder-Innit Method is called under the hood whenever you create a new instance of the class.
07:22
So when creating a new member, for example, our headmistress Miranda Muren, this Dunder-Innit Method is called automatically with Miranda's name, her birth year, and her sex. And the init method then returns an instance of the class which is assigned to a variable called Miranda.
07:43
Notice that the first argument of the Dunder-Innit Method is called self. This points towards an instance of the class whenever the method is called. And also to the class, we have added another method called says that adds behavior. So in this case, it allows our CastleKilmerMember
08:03
to say something. So when we call Miranda.says, hello my dear, Miranda will greet us. So these are notes about what I just said. And the Dunder-Innit Method is called under the hood when creating a new instance of the class. And as mentioned, its first argument is self,
08:22
which points towards an instance of the class whenever the method is called. So the CastleKilmer Member class is nice, but of course we want many other classes in our universe, like pupils, professors, ghosts, and so on. But these are all members of CastleKilmer, right?
08:40
So we can express this relationship using the concept of inheritance. Oh, sorry, I forgot to click on words. So inheritance allows us to create a new class that inherits all attributes and methods from the parent class. And the resulting child class can override methods
09:00
and attributes of the parent class, and it can add new functionality. Inheritance is great if you want to reduce duplicated code, but also if you want to show the semantic relations between objects. So let's use the concept of inheritance to create a pupil class. So this new class inherits
09:20
from our CastleKilmer Member class that's up here. And in the Dunder-Innit Method, we use this method super to call the Dunder-Innit Method of the parent class of the CastleKilmer Member class. And this initializes name, birth, year, and sex. Then we add new attributes, which are specific to our pupils.
09:42
For example, they start at school in a specific year and they might own a pet. And then there's another attribute here called ELMS, which stands for Elementary Level of Magic and contains all the obligatory classes a pupil has to take. So when creating a new pupil, she won't have passed any ELMS yet,
10:01
but of course this changes once he or she starts school and starts writing exams. Okay, so we can now create pupils. For example, our main character is a spin star. For this, we call the class with the necessary argument like name, birth year, start year, and so on.
10:21
So let's sum up what we learned in this first section. Classes in Python implement the paradigm of object-oriented programming. They act as a blueprint for an object and describe what properties and behavior an object should have. We created the class CastleKilmerMember and used inheritance to create a child class pupil.
10:43
And the child class inherits all methods and attributes from the parent, but can add new behavior and also override existing behavior. Then we talked about that inheritance is good for showing semantic relations and for avoiding duplicated code, but I have to say that you should be careful
11:01
not to use too many layers or levels of inheritance because it adds complexity and can make your code harder to read. And we now have CastleKilmerMembers and pupils, but we could equally use inheritance to create class like a professor and a ghost class, but for now we will stick with the pupil class.
11:23
Okay, so this concludes our first section. Now that we have some classes in our universe, I want to take a look at the different types of methods that we can add to a class. So a class can have three types of methods. There are instance methods, class methods,
11:41
and static methods. And we will start with the most common one, which are instance methods. Instance methods are the most common type of method. They take at least one parameter called self as an input which points towards an instance of the class when the method is called. We just learned about that in the first section.
12:02
An instance method can modify object state using the self parameter and class state indirectly when using the class or self.donda class parameter. And we have seen an instance method already in our base class.
12:21
So we have the says method, which takes the input self and a string of words, the Casa Kilmium member should say, and whenever the method is called on an object, the self parameter can be used to access attributes which were set in the donda init method, like self.name.
12:41
The next type of method we will look at are class methods. So class methods look similar to instance method in the sense that they take at least one parameter as an input, and this parameter is however not self but CLS, CLS for class, which points towards the class, not a particular object instance
13:01
when the method is called. And therefore, a class method can only modify class state but not object state. But of course now if you change class state, this affects all objects. Okay, so another important thing to know about class methods is that we have to use the at class methods decorator
13:22
when implementing a method, a class method. And we will talk about decorators later on. Right now, just remember that you put an at class method on top of the function, and we will see an example in a second. And one important thing to note first is that the names of the variable self and CLS
13:41
are only conventions. It's best to follow them, but in theory, you could also give these variables different names. Okay, so let's take a look at what class methods are good for. One nice way to use class methods is as alternative constructors. If you haven't heard of this before, you may now think, what is that supposed to mean?
14:02
So in Python, we can have only one constructor per class, the dunder init method, but we can use class methods to write functions that allow us to create objects that are configured exactly the way we want them. And in this way, they act as additional constructors,
14:21
these class method. For example, we probably want to create the main characters of our magical universe. And when we would have to type the names and attributes every time, this would be very slow and annoying. So we can speed up the process by adding a few class methods. In this example, we have a class method
14:41
for Lizzie, our main character. And with this, we can create the class method very easily by just calling pupil, which is the name of the class, .Lizzie, and this returns a perfectly set up instance of our main character. And you can equally create class methods for other characters like Luke, Barry,
15:00
or our headmistress, Miranda Mirren. Okay, last type of methods, we will look at our static methods. They take neither self nor CLS as an input, and therefore, they cannot modify object state nor class state.
15:20
But yeah, so they are related to the class, but they are still independent. And that's because they can only access data they are provided with. Static methods are a bit hard to understand, I think. So let's look at an example. If you remember the pupil class, we had this attribute called elms for elementary levels of magic.
15:42
And this contained all the obligatory classes a student has to take. And if the class is passed or not, depends on the grade that is written. So Castle Kilmer has a fixed grading scheme ranging from excellent to horrible. And this is actually perfect material for a static method.
16:02
So the static method we created here gets a grade as an input and then returns whether or not this grade means pass or fail. So you can see here that the method uses no class or instance state, but has access only to the attributes it's provided with, which is the grade it's given.
16:22
And we can now call this method on different pupils. For example, we can see if Lizzie passed when she writes an O, which stands for ordinary, or with an H for horrible. And since the static method is not bound to a particular object instance, we can also call it directly on the class pupil.
16:45
And one thing, another thing to note here is that we, up here, we use our newly created class methods to create the instances. So this already saved writing some code with the names and the other attributes of the two characters.
17:01
Okay, so you might now wonder why we don't use normal methods for these applications. So why do we really need class and static methods? A clear advantage of not only using instance methods, but also class and static ones is that they allow a developer to communicate what intention she had in mind when implementing the method.
17:21
For example, a static method expresses that the method is independent from the rest of the class. And another application for class methods would be that they can be used as alternative constructors. Okay, so this concludes our sections on the different types of methods that can be used in the class.
17:41
We have learned that classes can have three types of methods. The most common one are instance methods. Then there are also class and static methods. And one thing to note before we go on is that static methods or using them is quite controversial. So some people advise against them,
18:01
but personally, I think that in some use cases, they can be, yeah, useful. Okay, so going onto the next section, the next topic I would like to cover is the default DIC class. The default DIC class is part of the collections module. This is actually a really cool module,
18:22
and I suggest that you check out the other features it offers. For our magical universe, we will look at the default DIC class and how it's used. Okay, so let's say we want to extend the CastleKill member class with an underscore traits attribute. So we add a new attribute to the dunder init method,
18:43
which contains the character traits of a CastleKill member. And we further add function, which allows us to add attributes to our character, and then one which just nicely prints the traits. So with this functionality, we can add traits to Bromley,
19:00
or we haven't brought Bromley yet, and Bromley is the school's caretaker. So he's a very kind man who is tidy-minded since he's a caretaker after all, but there's something he's not, which is impatient. So we can account for this personality now by adding different traits to the Bromley instance.
19:21
So this can be seen here. And what we now want to do is that we want to add a function which checks if a CastleKill member exhibits a certain character trait or not. And as the type annotations here show, this function should accept a string, a trait,
19:42
and return whether or not the character in question or the person in question exhibits this trait. So what we want for this function is to return false if a certain trait cannot be found. And one way to do this would be to use the dig.get function,
20:01
but another even more powerful way is to use the default dig class of the collections module. Let's first look at the dig.get function. This allows us to provide a default value which is returned if a requested key cannot be found. So if a member possesses a trait, its value is retrieved from the underscore traits dictionary
20:24
and returned. If the key cannot be found, we just return false. So this would be a simple solution, but there's another one, namely the default dig class. So the default dig class is a subclass of the general dictionary type in Python.
20:42
It behaves like a normal dictionary in most cases, but has one important difference, namely that it accepts a callable in its constructor whose return value will be used if a requested key cannot be found. So when you access a missing key, this key is created and initialized
21:01
using the default factory. The basic usage is quite easy. We import the default dig class from the collections module and instantiate it by providing a default factory. The default factory must be some callable which returns a value, and the returned value will then be used
21:22
if a requested key cannot be found. So our goal for the exhibit trait function was to return false as a default value. This means that if a requested key cannot be found, which is a trait in our case, the default dig should create an entry for that key with the value false.
21:41
So how about providing false as the default factory when initializing the dictionary? So take a second to think about why this is not working. Okay, so we cannot provide false
22:01
as a default factory because the default dig class requires a callable as an argument. And the boolean false is not a callable, but a boolean. So a boolean variable. So instead, we have to define a function that returns false when called without arguments.
22:22
Such a function can be seen here. It simply returns false when being called. And with this, we can create our default dig by providing it with the return false function as default factory. Alternatively, you could also use a lambda expression here, but since we haven't talked about lambda expressions, I will stick to the normal function for now.
22:44
So what is so great about default digs? The current behavior. So right now we saw that there's the dig.get function and the behavior of our default dig right now is quite boring. So why do we need default digs?
23:00
The power of the default dig class arises from the fact that it can be provided with any kind of callable. And this has several important use cases. One common problem that can be solved with the default dig class is grouping items in a collection. So let's say we have a list of some of the pets Casa Kimia pupils are allowed to bring to school.
23:22
And we want to group the pets by type. So that means having all the owls together, the cats together and so on. And you can achieve this by providing the callable list as an argument to the default dict. So we create a default dict using list as a default factory.
23:41
And then we loop through our list of pets and our first item in the list is cotton. That's at the look of the hour of Luke and Lizzie's best friend. And when we try to find this key owl in the dictionary, it won't be found.
24:01
Since we try to find, so since we used list now as a default factory, a new empty list will be created and inserted into the dictionary for the key owl. We then append the name, which is cotton to the list. And next time we look for the key owl, it will already be contained in the dictionary. We can just append the new name to the list.
24:24
So what do you think the output will be when looping through the resulting dictionary, which we used for grouping the pets? Well, that's exactly what we wanted. We get a list of all the owls,
24:41
a list of all the cats and so on. So there are more use cases out there. For example, you could use a default dict to count the number of pets of each type. And I don't have this in the slides right now, but I'm confident that you will be able to solve it yourself. Okay, let's sum up what we learned. We started out with a common problem
25:02
that often occurs when working with dictionaries, namely accessing or modifying keys that don't exist. We learned that this can be solved using the collections.defaultDict class. A default dict behaves nearly identical to a regular Python dictionary with a subtle but important difference,
25:21
namely that it accepts a callable constructor whose return value will be used if a requested key cannot be found. And this can be useful in several situations. For example, when you want to group objects like we grouped our pets. Okay, so let's continue our journey
25:43
with a concept probably most of you have heard of, decorators. Decorators are quite advanced and can be a bit tricky to understand in the beginning. So don't worry if you don't fully understand how they work immediately. The more you use them and read about them,
26:00
the easier or clearer the concept becomes. So what is a decorator? In simple terms, a decorator is a callable that takes a callable as an input and returns a callable. What is a callable? So typically when we're talking about callables, we mean functions. So for simplicity, I will stick to functions from now on,
26:23
but you could equally decorate any other callable like a callable class, for example. So decorators allow us to extend and or modify the behavior of a callable and or of the callable that they take as an input.
26:40
And they do that without permanently modifying this input function or class itself. The behavior of the class only changed, sorry, of the method and this input function is changed only when it's decorated. So this sounds quite abstract. So let's look at some code.
27:01
The simplest decorator would be one that just returns its input function. Right now, this useless decorator is not doing anything. It receives a function and returns that function without modifying the behavior in any way.
27:20
Now we can apply a decorator to a function by wrapping it. So given our simple useless decorator, the one that is just returning the input function, we can apply it to our sayHello function up here by providing sayHello as an input and assigning the result to the variable sayHello again.
27:42
This way of applying decorators is quite cumbersome. As you can see here, we had to type sayHello twice here and here. So the more common way of applying decorators is to use this at decorator syntax, which is simply syntactic sugar that prevents having to write sayHello multiple times
28:03
in our case. So we could achieve the same behavior as before by just writing at useless decorator on top of our sayHello function. This is the same as when you create a class method or a static method with the at class or at static method decorator.
28:22
So right now, the output of the sayHello function is not changed at all since our useless decorator is not doing anything. So let's see how we can extend and modify the behavior of the wrapped function. So when we want to modify the behavior, our decorator must be a little more complex.
28:42
Specifically, it has to define a new function called the wrapper function. And this new wrapper function is then used to wrap the input function and modify its behavior. An example might look like this. So let's go through this step by step. We have our decorator function, which is called goodbye.
29:02
It accepts a function as an input and then defines this wrapper function internally. The wrapper function calls the given input function and stores the result in a variable called original output. It then appends the string goodbye, have a good day
29:21
to the original output and returns this new output. And then the decorator just returns the wrapper function. So when we apply this new decorator to our sayHello function, our output should have changed. So what do you think it is? So the output of this print statement.
29:45
I hope that's what you expected. So when our sayHello function is decorated with a goodbye decorator, the output changes to hey there, which is the original input. And after that goodbye, have a good day, which is the output or the string added by the wrapper function.
30:04
So this was a very simple function now without any input arguments, but how do we decorate a function that has input arguments since we also want to be able to decorate these kinds of functions. For example, we might have a function that allows a person to talk to another person
30:22
such that Lizzie could say hello to Luke. So how could we decorate this function? And what we have to make sure is that our goodbye wrapper function can somewhat, there we are, can somewhat process the arguments, person and words.
30:43
And this is actually not too hard. We simply use the arcs and quarks variables to collect all positional and keyword arguments and then forward them to the original input function. So our code looks similar to the previous version. The only difference is that the wrapper function
31:01
now collects all positional arguments in the arcs variable and all keyword arguments in the quarks variable. And these are then forwarded to the input function. The rest of the code stayed the same. And yeah, take a guess now at how the output of the print statement say words,
31:22
Lizzie, hey Luke will look like. Okay, so this works very well. So we can now decorate functions with arbitrary input arguments. And we won't dig deeper into the topic of decorators now. There's lots more to discover
31:41
and it would be a whole different talk to just go into the magic that can be done with decorators. So as a last piece of information, I want to ask you why you think or what you think why decorators are called decorators. I think that's a nice memory hook if you can't remember what they are doing. So think about that for a moment.
32:08
So actually we call them decorators because they decorate other functions and allow us to run code before and after the wrapped function is executed without permanently modifying its behavior.
32:23
And this closes our section on decorators. So as a quick summary, we learned that decorators allow us to modify the behavior of a function. We also learned that the decorated function only changes its behavior when it's decorated.
32:40
And this could be or can be very useful. For example, we could implement a decorator that determines how much time it takes for our code to run. And when using this decorator during development, we can time various parts of our code base, but remove the decorator again once we are done with all the optimization.
33:03
Yeah, the last point is that decorators are a really complex topic and that this only scratched the surface of this topic. Okay, going on, we have abstract-based classes. So we created several classes and methods in the past 30 minutes.
33:20
We have a parent class called CastleKimmiMember, several child classes. And as we learned in the beginning, the child classes inherit all methods from the parent class, but there are other more advanced applications where simple inheritance is not sufficient. And this is where abstract-based classes come into play.
33:41
Abstract-based classes are useful if your application involves a hierarchy of classes. In particular, in this hierarchy, it should be impossible to instantiate the base class, all subclasses should have a common base class, and all subclasses should implement certain methods defined in the base class. So before jumping to further explanations,
34:02
let's look at an example. In our magical universe, we have lots of different types of spells. For example, the spell could be a charm or a curse, and this makes the spell class a great application for Python's ABC module. To use an abstract-based class, we import Python's ABC module
34:21
and let our class inherit from the ABC class. And then we flag the methods that must be implemented by all subclasses with the decorator at abstract method. So a spell should have a name, an incantation, and a certain effect, and also it will have a defining feature
34:43
and a cast method. Notice that these implementations are abstract ones and not concrete. So the ABC tells you, or the ABC specifies the requirements of being a spell, but it does not tell you how to be a spell.
35:02
We can introspect an ABC to find out what abstract methods it has, and this is especially useful if the ABC you're working with is not your own. So let's test if we can instantiate the base class spell using a simple spell called Stuporus Raziato. For this, we call the spell class
35:21
with a name, an incantation, and an effect. So this actually doesn't work. It gives us a type error, which is exactly what we want, since for an ABC it should not be possible to instantiate the base class. So let's continue with creating a subclass.
35:41
So we create the class charm, which might look like this. It inherits from the base class spell, and naturally they're easy and difficult charms, so we will add two new attributes, difficulty and minimum here, where this specifies at what year students are able
36:01
or allowed to cast the charm in question. And we add an implementation of the abstract method cast. So let's try to instantiate this charm class, again, using Stuporus Raziato as an example. Okay, so we saw already
36:21
that we cannot instantiate our base class spell, but when we try to instantiate our subclass charm, it doesn't work either. So why do you think that's the case? So this instantiation statement
36:42
raises an error at instantiation time because we forgot to implement the defining feature method. And this highlights a big advantage of using abstract base classes. Let's say we have a subclass that doesn't implement all methods required by the base class.
37:00
When not using abstract base classes, we notice this only by getting an error quite late, when namely when we call the method that is missing. With abstract base classes, we get an error already at instantiation time. So for a proper implementation of the charm class,
37:20
we would have to add the defining feature method. So this implementation now contains everything that is required, an implementation of defining feature and the cast method. So we should now be able to instantiate the charm class, which works well, as you can see here.
37:40
Okay, so note, or an important thing to note is that ABCs only check for the presence of methods, not if they are properly implemented. So in our charm class, we could implement both required methods by just putting pass in the body and no logic at all. And when you notice yourself writing abstract methods
38:00
or not implementing them properly in several of your child classes, this is probably a sign that this method should not be an abstract method. Let's summarize what we learned. ABCs allow us to formalize the relationship between a parent and a subclass, and they serve three purposes.
38:21
First, they let the parent class communicate that subclasses should have a certain structure. Second, they allow classes to identify themselves as having the required structure, so that is meeting the demand requirements. And third, they enforce that a subclass meets the requirements,
38:40
otherwise throwing an error at an exceptional instantiation time. So lastly, I want to mention that also similar to decorators, ABCs are a huge topic and that you have seen now only a small part of it. But nevertheless, I hope that you have an idea now how they work and why they can be useful.
39:05
Okay, so our last section is coming up, which is about named tuples. So in this section, we will look at named tuples and before we do that, we should review what a tuple is. So in Python, a tuple is a simple data structure
39:24
that can be used for grouping arbitrary objects. It's important to know that tuples are immutable. That means that once a tuple has been created, it cannot be changed anymore. So we already use tuples in our magical universe.
39:40
For example, we defined the pet attribute of the pupil class to be a tuple, and each tuple has two fields, the name of the pet and the type. So Ramses, Lizzie's cat would be an example of such a pet. Each field of this tuple can be accessed using its integer index. For example, we can get the name of Lizzie's pet by looking at the value at index zero.
40:03
As I already mentioned, tuples are immutable. So once we create a tuple, we cannot change it anymore. And you can see this in the example on the slide. When we try to change the name of Lizzie's pet to Twiggles, we get a type error that tells us that we cannot assign new values to the items of a tuple.
40:23
So what are named tuples? As the name suggests, they are a variation or rather an extension of plain tuples. In particular, they allow us to name the fields of the tuple, which makes it easier to access the individual fields, and it makes our code more readable.
40:40
So in the plain tuple example, we were only able to access the values stored in the tuple by using integer indices like Lizzie's pet at position zero, which is fine when not having too many fields, but becomes messy when having three or more fields in the tuple. So how can we create a tuple, a named tuple?
41:02
This is quite easy. There are two kinds of named tuples, the collections.NamedTuple class and typing.NamedTuple. And due to lack of time, we will only look into typing.NamedTuple right now. So this use a very easy syntax and allows us to specify the type of each field,
41:22
and it makes it easy to add methods to the class. An implementation of the pet class as a named tuple would look as follows. Our fields stay the same. Each pet has a name and a type, and these are both strings. And when implementing typing.NamedTuple,
41:41
we actually get some methods for free, like we can print instances and get a nice representation of them. We can now access the fields by using either field names or their indices, which is especially helpful and makes our code more readable. So let's think about our magical universe.
42:01
We don't want our pupils, professors, or ghosts to be immutable. For example, the pet of a pupil might change, but a suitable group of people for an immutable class are the dark army members. And why is that the case? Because once you become a member of the dark army, there's actually no way back.
42:20
So each dark army member will have a name and a birth year, and we can further specify that Master Odon is the leader of the dark army. And now we can easily create members of the dark army. For example, Keras Fallford, who's one dreaded member, and we can access the leader, Master Odon, either here on the Keras instance.
42:45
So for example, what you can also see here is that you still cannot change attributes like the name, and we made sure of this by seeing that we get an attribute error when we try to change Keras name into Mortimer.
43:02
Okay, so we're nearly done. Quick summary. Let's recap what we learned. Name tuples are an extension of plain tuples that present a shortcut for creating immutable classes, but they are not the only ways. So starting from Python 3.7, you can also use data classes for this,
43:22
but we don't have time left to talk about data classes. So what I want to give you for the end or when finishing this talk is that the topics that we now discussed are only a small portion of the features and topics
43:41
that I worked on in the magical universe. So if you go and check out the GitHub repository or the corresponding blog posts, there are lots of more cool applications and Python features implemented using the universe, like for example, data classes, but also custom exception classes and lots of other things.
44:02
And yeah, thanks a lot for listening. I hope you enjoyed our quick journey through this magical universe today. And the most important thing I want you to remember is that learning can actually be a lot of fun if you find a topic you're interested or passionate about, like for me, Harry Potter,
44:20
but for you, maybe something completely different. Thank you, Annalena, for that very fun talk. Although the time is up, but there is a brief question that we can take.
44:40
So let me just, what age are the students you're teaching these Python concepts to and do they have previous coding experience? Yeah, okay, so they don't need any previous coding experience. I guess what you're talking about now is this Caim Machtuhle EIGO School I talked about briefly in the beginning.
45:02
And they're the kids at the moment are between the ninth and 12th grade in German schools, but we are actually extending also our portfolio of courses to younger kids, but then you need a completely different approach since for AI, you need some mathematical background knowledge
45:20
and that's what we are still using at the moment. But yeah, you can definitely participate in the courses if you don't have any coding experience or knowledge about AI and coding. All right, that's very exciting. And thank you for the great talk. You can connect with the audience
45:41
in the breakout optiverger room. Definitely, I will do that. See you there, thanks. See you.