Metaprogramming, from decorators to macros
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 | ||
Part Number | 47 | |
Number of Parts | 119 | |
Author | ||
License | CC Attribution 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/19939 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Production Place | Berlin |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
| |
Keywords |
00:00
Macro (computer science)TwitterComputer programmingMeta elementLink (knot theory)TwitterCodeCountingSlide ruleOpen setComputer animationLecture/Conference
00:43
Social classMeta elementMacro (computer science)Computer programmingAbstract syntax treeComputer programRun time (program lifecycle phase)MetaprogrammierungSlide ruleComputer programmingMomentumMultiplication signProcess (computing)Parameter (computer programming)MereologyWritingDifferent (Kate Ryan album)Software developerMetaprogrammierungRun time (program lifecycle phase)Lecture/ConferenceComputer animation
02:23
Product (business)Line (geometry)Domain nameComputer programmingAbstractionSlide ruleCodeLecture/Conference
03:02
Meta elementDrop (liquid)Computer-generated imagerySample (statistics)Price indexGastropod shellObject (grammar)DivisorSoftware engineeringTorusSineHill differential equationConvex hullInternet forumOvalFunctional programmingParameter (computer programming)WordExpressionInterpreter (computing)Process (computing)Form (programming)Video gamePoint (geometry)NumberRecursionFunctional programmingMultiplication signProgramming languageBranch (computer science)Analytic continuationComputer animation
04:57
Function (mathematics)Performance appraisalSymbol tableNeuroinformatikElectronic mailing listLimit (category theory)System callVariable (mathematics)Form (programming)SineElement (mathematics)Trigonometric functionsPerformance appraisalProduct (business)Computer programmingCategory of beingMoment (mathematics)ExpressionOperator (mathematics)Set (mathematics)Branch (computer science)Arithmetic meanMultiplicationFunctional programmingMacro (computer science)Representation (politics)Multiplication signPoint (geometry)Sampling (statistics)Parameter (computer programming)Sign (mathematics)Cone penetration testCodierung <Programmierung>Level (video gaming)Programming languageComputer animation
08:28
CodeMeta elementDivisorFunction (mathematics)Variable (mathematics)BacktrackingPerformance appraisalRepetitionThread (computing)Personal digital assistantSensitivity analysisFunctional programmingForm (programming)BitDifferent (Kate Ryan album)Image resolutionComputer animation
09:07
Function (mathematics)Macro (computer science)Abstract syntax treeDifferent (Kate Ryan album)Equaliser (mathematics)Pattern languageFunctional programmingSocial classInteractive televisionExpressionPosition operatorMultiplication signComputer programmingDirection (geometry)Run time (program lifecycle phase)Macro (computer science)Meta elementAbstract syntax treeComputer animation
11:00
Equivalence relationFunction (mathematics)Letterpress printingFile formatDean numberKey (cryptography)Endliche ModelltheorieMeta elementSoftware testingGastropod shellProcess (computing)Physical systemDefault (computer science)Data typeInformationInteractive televisionAsynchronous Transfer ModeSpecial unitary groupModule (mathematics)Directory serviceCodeData bufferSlide ruleData conversionGUI widgetBit rateThermal expansionLambda calculusOrder (biology)Attribute grammarMultiplication signResultantFunctional programmingLetterpress printingData storage deviceHardy spaceMessage passingFunctional programmingType theoryTotal S.A.Prisoner's dilemmaSocial classCondition numberState of matterConnectivity (graph theory)Lecture/ConferenceComputer animation
14:24
CodeFunction (mathematics)Letterpress printingFile formatFunktorGastropod shellData buffer10 (number)Hand fanPositional notationMoment (mathematics)Electronic signatureKey (cryptography)Meta elementEndliche ModelltheorieSoftware testingAvatar (2009 film)Execution unitDreizehnoutputSocial classDependent and independent variablesLambda calculusInstance (computer science)Equivalence relationSoftware testingInheritance (object-oriented programming)INTEGRALDifferent (Kate Ryan album)Radical (chemistry)QuicksortFunctional programmingAlgorithmTheorySocial classMathematicsMultiplication signBitDependent and independent variablesElement (mathematics)ResultantTerm (mathematics)Invariant (mathematics)CodeContent (media)LiquidGroup actionEndliche ModelltheorieSource codeRun time (program lifecycle phase)CASE <Informatik>Product (business)Electronic signatureImplementationType theoryComputer programmingModule (mathematics)MetaprogrammierungTupleMeta element2 (number)NP-hardMessage passingXMLComputer animation
20:19
Social classInstance (computer science)Equivalence relationFunction (mathematics)Meta elementoutputCodeDynamische GeometrieUsabilitySpecial unitary groupObject (grammar)Data typeParameter (computer programming)TupleEndliche ModelltheorieDefault (computer science)Boilerplate (text)InformationIntegerAttribute grammarEquals signHacker (term)Field (computer science)Data modelSample (statistics)Category of beingType theorySocial classBitFunctional programmingCodeSampling (statistics)ImplementationObject (grammar)Data storage deviceSoftware frameworkRun time (program lifecycle phase)IntegerField (computer science)Military baseCategory of beingObject-relational mappingInformationEndliche ModelltheorieMessage passingSoftware testingDefault (computer science)Data dictionaryElectronic mailing listDifferent (Kate Ryan album)Multiplication signMeta elementCASE <Informatik>Element (mathematics)String (computer science)TypprüfungDatabaseSlide rulePoint (geometry)Inheritance (object-oriented programming)Attribute grammarBoilerplate (text)Parameter (computer programming)Instance (computer science)Volume (thermodynamics)Hazard (2005 film)Compilation albumForm (programming)Basis <Mathematik>Exception handlingMögliche-Welten-SemantikNominal numberDomain nameObservational studyVariable (mathematics)Lecture/ConferenceComputer animation
27:06
Process (computing)Key (cryptography)Data bufferEndliche ModelltheorieMeta elementSoftware testingSI-EinheitenField (computer science)Data modelString (computer science)Data typeReliefError messageDefault (computer science)Category of beingNormed vector spaceInversion (music)CNNLatent class modelElectronic data interchangeException handlingUniform resource nameInstance (computer science)Simplex algorithmFunction (mathematics)Parameter (computer programming)Endliche ModelltheorieSocial classInstance (computer science)Object (grammar)Type theoryException handlingAttribute grammarFunctional programmingField (computer science)Electronic mailing listMultiplication signTypprüfungInheritance (object-oriented programming)Loop (music)BitLocal ringString (computer science)Constructor (object-oriented programming)Message passingDifferent (Kate Ryan album)IntegerMeta elementSet (mathematics)Slide ruleExecution unitMathematical analysisTask (computing)MetamodellCondition numberKey (cryptography)Cellular automatonVideo gameBasis <Mathematik>Computer animation
32:29
Inheritance (object-oriented programming)Data typeCodeComputer fileMeta elementPatch (Unix)Software testingEndliche ModelltheorieVariable (mathematics)RippingFlagParsingNetwork topologySource codeAsynchronous Transfer ModeCompilation albumString (computer science)Host Identity ProtocolFunction (mathematics)Computer virusLetterpress printingJunction (traffic)Hash functionData bufferSparse matrixPower (physics)Functional programmingStreaming mediaSource codeMacro (computer science)Multiplication signLibrary (computing)Social classObject (grammar)DialectBitImplementationString (computer science)Inheritance (object-oriented programming)Term (mathematics)Order (biology)Module (mathematics)FlagContent (media)Equaliser (mathematics)Error messageVariable (mathematics)Thread (computing)Run time (program lifecycle phase)TheoryGoodness of fitMeta elementVarianceNetwork topologyAbstract syntax treeComputer animation
36:27
Point (geometry)String (computer science)Macro (computer science)Core dumpEndliche ModelltheorieCodeImplementationSlide ruleComputer programmingObject-relational mappingSocial classFitness functionMacro (computer science)CodeMetaprogrammierungSlide ruleCASE <Informatik>InformationExecution unitComputer-assisted translationSystem callComputer animation
37:15
Programming languageMacro (computer science)Software maintenanceMetaprogrammierungLogic gateSerial portLecture/Conference
38:46
Semantics (computer science)Macro (computer science)Function (mathematics)Mechanism designTransformation (genetics)Abstract syntax treeSocial classWebsiteImplementationComputer programmingProgramming languageComputer animationLecture/Conference
Transcript: English(auto-generated)
00:15
So, hi, everyone, this is my Twitter account, and this link here that you can see, you can
00:21
already download all the material I'm going to show, there will be the code I'm going to show and the slide source, so you can have a look and play around. You're welcome to open Python and interactively try the examples I'm going to show you, because that's what I will do as well. So, I come from Italy, but I live in London, and I work for this company called Dipop,
00:43
this is just a small advertisement slide where I tell, just telling you that we are hiring, we're looking for API developers, and if you're interested, just have a look there, dipop.com, jobs, we're using Django, Celery, all nice things, MongoDB, Postgres, et cetera, et cetera.
01:02
All right, so what are we going to talk about today? So, first of all, I'm going to try to define what is metaprogramming and why it is useful, and then we are going to talk about Lisp a little bit, but not too much, so don't be scared, and then we're going to talk about Python and how some techniques we can use for metaprogramming
01:23
in Python. So, this is the definition I found on Wikipedia about metaprogramming, I don't know if it's the best one, but let's try to go with this one. Metaprogramming is the writing of computer programs that write or manipulate other programs or themselves as their data, or that do part of the work at compile time that would be
01:46
otherwise done at runtime. So, this is kind of still not very clear, but I think we're going to see now in some examples how this, what this really means. I manipulate the program itself, manipulate themself, well, I don't know, I'll show
02:06
you later what that means. So, why on earth would you do that? That's the most important question, because that sounds really magic and really strange. There are some scenarios where this really makes a big difference, and normally it's
02:20
used, it's not really used for performance reasons or for making a better product, it's maybe normally just used to be closer to the domain you're working in, so you write an abstraction in a more powerful way, and in the end you manage to minimize the line of code you have, or you manage to make the whole program more close to your domain,
02:46
and more easy to understand for the people in that domain. So what's the cost of that? Well, if you do it well, nothing. If you do it wrong, you might screw yourself up a little bit.
03:00
So next slide. Just a very small introduction to Lisp, so it was invented by McCart in 1958, so that was a very long time ago, it's the grandfather of languages in a way, and what people think about it is that there are lots of parentheses, that's how people see it normally.
03:23
There is a reason, however, for all these parentheses, and then I'm going to try to show you what it is. This is the simplest possible, well, the simple factorial function, and this is how it's defined. There is a special form defined, which is a way of defining functions, which takes
03:46
an argument, which is the name of the function, the arguments of the function, and then there is another special form if, which takes three arguments, the conditional, the then, and the else branch here.
04:02
And all these things are expressions, as expressions to be precise. I'm going to do a lot of kind of live coding, so maybe I'll try now for the first time to just show you how things actually work. So we go in Emacs, yeah, of course, and I define, this is the replica for SBCL, which
04:30
is a common Lisp interpreter, and then I here I define factorial, I compute it, everything works fine.
04:40
Interesting thing to note is that even if I give a very high number, it doesn't blow up like Python would do, even if it's recursive, because it's smarter about recursion than Python. So let's continue. So Lisp has very small, very limited syntax, and there's another property, which is quite
05:04
uncommon and not of many languages, which is homoeconicity. That's a very difficult word, not easy to define, but practical means that the program itself is a valid representation of the data.
05:22
So here, for example, what we have is the computation of the product between the sine of one and the cosine of 2.03. And what this actually means is that it's like setting an expression to a list where the first element of the list is a symbol star, the second element is another list
05:44
with symbol sine and 101, and the third is another list with cosine and 2.03. And then you evaluate that expression. So why is homoeconal that word? This because you can actually transform and pass around a program and manipulate it easily
06:03
as it was data. So to make it more, maybe more clear, I try to say, how is Python homoeconal? Well, no, but how would it look like if it could be, for example? That might be something, I don't know if that makes sense, but suppose you can write,
06:23
suppose this is valid Python, this is a way to define a function. You create a list, and then the first element of the list is def, then you have function, then you have arg, and then comma pass. So this is a list, and this is also how you define a function. It's not true, of course, but that's what it would look like if it was.
06:45
So why this thing is so important? Well, first, this is just to show how the evaluation is done in Lisp, just to be clear. As you know, every operator is infix, and then everything is cons in the end.
07:00
So you have here the star, the multiplication sign, then you have the two, then you have another branch where you have the plus, the three, the four, and here nil, a nil, because there is no other element in the cons. So why is this property important? Because in Lisp you can make programming to a very deep level, you can make using macros.
07:28
So assume, which you may have ever seen, but in Lisp to set, to do an assignment of a variable, you do set q x 10, for example, which sets to the symbol x the value 10.
07:42
Suppose I want to do something like set 10 to two variables at the same time, like assigning two things to one value in one call. Is that possible? Well, at the moment it's not possible, but what if I write a function, so I write this
08:01
function define set q f x y z, and then I do this, I use this special form program which concatenate to multiple expressions, but within them. But that doesn't work, so we can try it out, see what happens.
08:25
Where was it? Set q. So now I do set q to f, I do a, b, and then I say 10.
08:46
It fails, it says the variable a is unbound. So well, how do I solve it? But that's kind of understandable in a way, because I'm trying to set, to create a special form with the function, so that's not really possible.
09:02
So, however, if I rewrite this thing with the macro, where the only difference is that here I use def macro, and here I use this back quote, and these commas here in front, instead everything works fine.
09:23
See, I define the macro, and then I do set q to a, b, a, b, everything works. So what's the difference? The difference seems small, but it's quite relevant, because here, this macro is basically creating compile time, a new function that will get be templated when you call it.
09:49
So this is like, it takes the symbol, it doesn't try to evaluate it, it doesn't try to evaluate a or b, it just passes around to this quoted thing, which then gets evaluated
10:01
at runtime, and this runs normally, as it should. So a very powerful technique. Can we do the same in Python? Almost. Well, I mean, to do this kind of thing, you could do something like that, which is horrible, and yeah, almost works.
10:21
So basically, you pass two strings, like a and b, and then you pass an expression, you evaluate the expression, and then you update the globals with this thing. It's not even the same, exactly, but it kind of works, but yeah, don't do that.
10:42
So yeah, the Lisp prior introduction is over. We can pass something more interesting in Python. So what can we do in Python for metaprogramming? We can have function decorators, class decorators, meta classes, and then if you really want to be fancy, you can manipulate the syntax tree.
11:04
I'm going to show them in order. They are also in order of difficulty in a way. What is a decorator first? A decorator is just a syntactic sugar for a function that modifies the behavior of another function or a class.
11:21
So this simply means this below. You do an at decorator as the function, and the same thing as defining the function and then redefining, assigning it to the return result of the decorator itself.
11:40
And let's see the first problem that we try to solve with decorators. Assume I want to measure the time spent in a function and print it out to the standard output and see how long everything takes. This is a decorator that does it. So it takes the function, it uses this nice wraps decorator, define it in functools,
12:06
and this is just to make sure that all the underlying attributes like doc and so on gets passed correctly and they don't get lost along the way. It would work anyway. It's always good to put this.
12:21
So yeah, and then you define an inner function which will call the original one, store the result somewhere, store the time before and after, and then print out the time spent and return the original result. And then here you return this inner function.
12:43
You can show this how that works. So now we go to the shell, I open it, I type it in. Can you see in the back?
13:00
Bigger maybe? Next, okay, okay, okay.
13:23
What was it called? Decorators, time, I print, okay. So now I create another function, time it print. There's something, time me, doesn't do anything useful.
13:47
Then I call this and I get this message here. Function time me took, they should have said something else. Ah, because I changed it before the talk of course and I made a mistake.
14:08
This, sorry, no, still the same.
14:33
Ah, yeah, yeah, yeah, thank you.
14:51
All right, I can reload the decorators, so this works, no. What? No, just R.
15:08
Okay, let's do, I showed you the next example, it's more interesting. All right. Okay, so we have another problem.
15:21
I'm still with timing but slightly different because I want to know when I'm implementing something new, like a new feature or I change the algorithm, I want to know that the new one runs faster than the previous one. But I just, I don't want just to know it once, I want to make sure this always like that, so I want to have that running in a test somewhere, like integration test
15:44
and say my new fancy algorithm is still faster than the crappy old one after six months of hacking on it and adding things. So well, I mean in theory with the previous approach we couldn't do that because we were
16:00
just printing it out so we can't just check all the time how things look like. But with another decorator which also changed the signature of the original function, then we can do that. So what I have here is a test to check that the first implementation is faster than
16:20
the second one and the way it works is that the new, this decorator here will change the function return values and add the time spent in the function as a second return value. And so I do this, I do this for the second one and then I can check that the time of
16:43
the first one is less than the time of the second one. So now let's see how we actually implemented them. So still quite simple, actually exactly the same almost. The only difference is that here when we do the return we also add the time here.
17:06
So this is an interesting case and the difference is that you can't use it in an import time way because if you decorate your function in the module like that then it will mess
17:20
up everything because you don't care about the time spent in production. So you can only do that in this way but it's perfectly valid thing as I was saying since it's just in TatiSugar to just replace the function at runtime in this way and then call it. So let's see if this, I have more luck with this one, so decorators, oh yes that works.
18:09
So yeah, see I get a tuple and the first element is the result and the second element is the time spent, very nice. To actually see how things work, it's interesting also to look at the code here of time me
18:30
and yes and the wraps function did a nice thing to also make sure that the source code that is returned is the original one not the wrapped in the decorator.
18:47
Alright, so another example, this is how you can decorate a class instead, suppose I want to add always the same method to many classes and this, I mean, I don't want to go in every
19:02
class and change it and I don't want to make a super class to make this, this is another very simple way to do that, you just, this is the test where I have a class which adds a response method and then when I associate this class and I call response
19:21
I get the return I want, the value I want. So this is the simple way you do it, very clear and simple. You just take the class here, you assign to response an anonymous function which takes self and returns this and then you return the class itself.
19:43
Yeah, that's all for decorators for now. So let's pass to meta classes. Meta classes is the next way of doing meta programming in Python, it's more powerful and it's more, it's also a bit more difficult to understand in the beginning but it's really not that hard, as hard as it looks as I'm going to show you.
20:05
So what's a meta class? Well, a meta class in Python is just the same as a meta class tends to a class like a class tends to an instance, so it's a type of a class.
20:20
If you create a class in this way here, it's exactly the same thing as doing it in this way with the type function. I'm going to try to show you now a little bit. For example, if I now do this, I forgot to mention in the beginning that all the code
20:41
I'm showing is Python 3 only, well the difference is not many but yes, if you try to run it on Python 2 it might fail or it might not do what you want. Okay, so what's the type of C? Type.
21:01
And then if I try instead to create a type, let's see what this takes as an argument, it takes an object or name, a list of bases and the dictionary. So for example, suppose I want to create a runtime, a class like B, which has bases
21:23
on the object and then as dictionary I have a class attribute A10, must be a tuple, yes mistake, okay, so this is now a class and I can instantiate the class and I can access
21:47
the attribute A. So this is another way of creating classes at runtime and this is how in the background it works. Let's see the simplest possible meta class implementation and how to use it.
22:05
So we have a class simple meta which subclasses type and then to use it in our own class we only need to create class subclassing object and then passing meta class equal to simple
22:21
here. In Python 2 it would have been underscore underscore meta class here equal to something, but it's just the same thing. And now let's pass through some more interesting examples I think.
22:41
In every ORM or every Django framework or something, it's very easy to define models that talk to database, store data, keep some information about the type and so on and this is kind of possible syntax that is used which I just made up but it's quite similar
23:03
enough I think and it looks like magic but it's not that hard to do in reality and the simple way to do it in this case if I want to accomplish something like that, if I don't have meta classes, I could just have a model for this particular case
23:24
which takes the argument x and y and then initialize them like that. So well I mean you can do that if you have some very simple scenarios but if you want to define many models, if you want it's very verbose because every time you have
23:42
to declare everything and assign it there is a lot of boilerplate and also the very important thing I think is that you have no information about the types and while Python is duck type, databases are normally not so you still need to have the information somewhere.
24:02
So how can we accomplish this kind of very nice thing in Python then? We start by looking at how we can implement a field type so which is this one. So a field type will be a base class
24:22
for things like integer or string and you can implement it so this is the test that will this the requirement for this kind of type. I want to have three different things I want to be able to wait a minute I'm not this there's not the right test okay this one
24:45
is like this sorry sorry no take it back this is the next slide. So this is the the model I want to have and these are the three requirements that I have for this model to behave like I want. So I want to be able to create an object like this passing for example y
25:08
and without passing x, x has default value y doesn't have one so I checked that after I pass this y is set and x is also set to the default value. I want to be able to know that
25:23
if I pass something wrong like unknown hello it will give an exception and if I pass something of the wrong type it will always give a type error in this case. So first we can look at how fields are implemented and here again there's a requirement for the fields so if I create an
25:44
integer where I pass zero as value and the default one the value will take the precedence if I try to set at the init time something which is the wrong type I get the type error and also very importantly if I in the beginning create the element correctly and then I change
26:04
the type to something else and then I also get a type error. Let's say an implementation of fields first which is not you done using metaclasses but it's done in this way so they need the most important thing is that we have a property here which has a also a setter
26:29
and this property is the actual representing the value and whenever you try to set here the value which is also done at this point it will always check the type it checks if the type is not
26:46
an instance of this base type whichever class will have to define then I raise a type error let's see how is for example the implementation of a string or integer so very simple here we have
27:06
the base class here is integer and here is string so that's all all I have to do is to define the base type and if the object or passing is not an instance of that then it will give type error. So let's go back now to the model the model's metaclass and this is the actual
27:30
instead the solution for all this which fits in the slide so it must not be that difficult is the solution for the original problem. The way it's done is that a subclass type
27:44
as I've done before in the previous example and then I override the __new method which is used to in during the construction of the class itself instead of the initialization initialization of the object like init
28:01
and then I get four arguments here I get the class I get the name I get the list of base classes and I have this important the class dict which is all the the attributes and methods of the class basically which we can modify.
28:25
So the way I want to do this is basically just replacing the init of the new class that I will create now with another init that will do some extra checks and extra
28:40
things for me automatically every time. First of all I loop over the attributes of the class and I check if the if the attribute of the class is an instance of a field then this is a field I just stored it in a dictionary here and then I redefine an init here which
29:04
takes some KWX so it can take X equal one Y equal two and so on and so forth and then it will first of all check if there are some arguments which I pass in that are not known so if the set of the difference between the K the arguments passed and the fields that
29:27
found looking inspecting the class is greater than zero then give an exception otherwise if not if everything is fine then loop over this and then generate
29:43
set an attribute to this object self with the as a key the name of the the argument and there's a value the value which I just now created by calling the class and passing
30:02
the value so sounds more complicated than this maybe but I try to show maybe now how it works and then after that the important step is that I redefine the init of the class take to the thing which I already defined here and then I return just the super call and try to show you
30:28
just very simple how this behaves maybe so if I now yes now the only thing I need to do
30:41
is to define a model in this way class model yes and then I will simply if I define now another model um oh that's sorry type today but for model and then I define x equal to models
31:28
string okay now suppose I want to create an instance of this but I pass the wrong thing complaints and no arguments y if I pass this it checks the type and there's another
31:45
if I pass this instead everything will work correctly oh sorry and the interesting thing if if I look at the init of this method it tells me where actually it comes oh no sorry
32:02
if I look at this if I look at the init of the class simple too it tells me that it comes from here function models meta model new locals init so that's where it finds it all right
32:23
another another example which is a bit more simple is how to for example make sure that we always call the super of the init in the subclasses of a super class that we define um I've seen this doing for example in the module threading.py if you forget to call the init
32:42
it will blow up and complain and if you look at the implementation it's basically just this it has initialized false and in init it will set initialize true and in every method that has to be working on an initialized object there is this check so that's a bit
33:02
annoying and that's a bit too long maybe to do so this is what I want is that I call something and if I forgot to call the super in the init it should give me an assertion error and that's it that's the implementation very simple I do I store the original init somewhere
33:28
and then I call it here I replace the init with another init which I'm doing I call it here just to make sure I don't lose anything and then I also add an assertion looking for a flag variable
33:43
that is set so this is kind of doing the same thing but it's in a more generic way and so all you have to do in your class to use this is to just go um here I define a class base passed
34:02
in the meta class checking it and all I have to do is to define a flag variable equal var and this is a variable that I know that I always set in the init here so if something tries to subclass base and forget to call init this here will be not set
34:25
and then this will give an assertion error yep and last thing I want to show very quickly is that just you can do even much worse than that if you want and this is a very simple function that analyze the aest of a given function
34:50
parsing it parsing the source and then trying to find out a particular value a string and replacing it with something else to show you the actual example is probably easier to
35:05
understand this is um this is the function here which I want to replace a runtime and what I want to replace is to remove the hello from the string so and this is what it's doing I call it I exec this um the return of this and then I call it again so what is going to happen
35:37
is that I don't know yeah the first time it calls with hello world the second time only one
35:47
all right everything works fine um so the thing is that of course this is very hard-coded and it's not really uh the good idea but in theory ast is just a tree so you can traverse it in any way you want so you can look for all the things that look like strings
36:04
adapt this content or you can look for all the you can do anything you want and you can put that in a decorator or you can and in this this is the only way I think that you can reach something like as powerful as lisp does in python and there is a library which I'm going to
36:22
I don't have time to show because I knew it was too much there is a library called macro pi where you can actually do things like that and this is valid python even my syntax highlighter doesn't think it is but it will run and it will work and you can make a case class where you declare a class like that passing x and y and this automatically will
36:44
create a init with x and y and you can just instantiate it like that and everything will work correctly and that's how it's implemented so if you want to look it up it's called macro pi so yeah that's it for me so any questions and then just the conclusion sorry uh well
37:04
meta programming is fun you can make it in just one fit in one slide the code to create a simple style orm and then just be careful but uh yeah use it if you want
37:35
yeah would you still be using metaprogramming and yeah sorry if I knew that the maintainer
37:47
might be a psychopath and serial killer would I still be using meta programming uh yes but I would comment it maybe leave out my name or uh or change the history of gate to make sure it doesn't come to me yeah
38:07
another question
38:20
I think the philosophy of python is that you shouldn't do things that are too unreadable and too hard to understand so it would kind of go against the the language design to add more and I don't know what really you could but there are things you can do crazy things like
38:40
macro pi does so it is possible already it's just I think it's enough and I wouldn't think you need more than that yeah thank you