Metaclasses for fun and profit: Making a declarative GUI implementation
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 | 58 | |
Number of Parts | 169 | |
Author | ||
Contributors | ||
License | CC Attribution - NonCommercial - ShareAlike 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 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/21094 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
00:00
ImplementationGraphical user interfaceDeclarative programmingGraphical user interfaceMultiplication signDeclarative programmingImplementationCommunications protocolLecture/Conference
00:31
Meta elementSocial classOpen setGraphical user interfaceImplementationDisintegrationPhysical systemDatabaseEmailTime domainQuicksortBitBit rateEndliche ModelltheorieComputer animation
01:18
User interfaceMeta elementSocial classDependent and independent variablesType theorySocial classTask (computing)Key (cryptography)WordLecture/ConferenceComputer animation
01:50
User interfaceMeta elementSocial classBitLibrary (computing)Form (programming)CuboidMultiplication signWater vaporWordSoftwareArmElectronic visual displayLetterpress printingUser interfaceComputer animationLecture/Conference
02:32
Metropolitan area networkDiscrete element methodUser profileLine (geometry)Maxima and minimaPeg solitaireGraphical user interfaceData typeLibrary (computing)Social classWrapper (data mining)Object (grammar)CASE <Informatik>User interfaceCartesian coordinate systemProcess (computing)Electronic visual displayComputer animation
03:41
Graphical user interfaceSocial classSummierbarkeitCAN busMetropolitan area networkMenu (computing)Special unitary groupData modelMeta elementMobile appInfinityMUDWindowCuboidQuicksortHierarchyMetric systemLevel (video gaming)Group actionWindowMultiplication signGUI widgetCodeDifferent (Kate Ryan album)Pairwise comparisonMereologySpacetimeUser interfaceRight angleType theorySocial classFitness functionSlide ruleGraphical user interfaceMeta elementComputer animation
05:05
Social classMeta elementData typeMountain passObject (grammar)CAN busSocial classMeta elementInsertion lossCodeEndliche ModelltheorieBeat (acoustics)Task (computing)Metric systemInstance (computer science)Parameter (computer programming)Different (Kate Ryan album)BitLecture/ConferenceComputer animation
06:27
Social classMeta elementObject (grammar)Social classMathematicsInsertion lossMeta elementConstructor (object-oriented programming)CASE <Informatik>Lecture/ConferenceComputer animation
07:00
Meta elementSocial classInstance (computer science)Order (biology)Execution unitSoftware testingOpen setSpacetimeObject (grammar)Instance (computer science)Social classMessage passingInsertion lossSource codeFrequencyIntegerComputer animation
07:35
Meta elementSocial classInstance (computer science)Order (biology)Execution unitSoftware testingSpacetimeMeta elementSocial classObject (grammar)NamespaceStandard deviationInstance (computer science)Declarative programmingOrder (biology)Lecture/ConferenceComputer animation
08:26
NumberArithmetic meanDifferent (Kate Ryan album)Parameter (computer programming)Inheritance (object-oriented programming)Electronic mailing listConstructor (object-oriented programming)Interior (topology)Lecture/Conference
09:00
Social classMeta elementInstance (computer science)Order (biology)Software testingExecution unitSpacetimeOpen setMountain passAttribute grammarError messageRight angleInstance (computer science)Social classMeta elementCASE <Informatik>Cellular automatonInsertion lossComputer animation
09:35
Meta elementSocial classMountain passAttribute grammarError messageData typeOpen setObject (grammar)Instance (computer science)Social classRight angleMeta elementDeclarative programmingCodeResultantDifferent (Kate Ryan album)Lecture/ConferenceComputer animation
10:28
Social classMeta elementData typeMountain passObject (grammar)Social classMeta elementDeclarative programmingSource codeObservational studyPower (physics)QuicksortStandard deviationGraphical user interfaceLecture/ConferenceComputer animation
11:14
Meta elementPairwise comparisonSocial classWindowCuboidMulti-agent systemPairwise comparisonDeclarative programmingSource codeGreatest elementLecture/ConferenceComputer animation
11:46
Order (biology)Social classAttribute grammarMeta elementElectronic mailing listObject (grammar)Level (video gaming)Right angleCodeAttribute grammarOrder (biology)Computer animation
12:19
WindowMereologyWater vaporBitNumberLecture/Conference
12:50
Order (biology)Attribute grammarMeta elementSocial classElectronic mailing listObject (grammar)Level (video gaming)Social classAttribute grammarInstance (computer science)BitMeta elementSlide ruleSinc functionCartesian coordinate systemComputer animationLecture/Conference
13:51
Pairwise comparisonSocial classMeta elementWindowCuboidOrder (biology)Attribute grammarElectronic mailing listObject (grammar)Level (video gaming)Group actionSocial classOrder (biology)Electronic mailing listNamespaceMeta elementAttribute grammarMobile appComputer animation
15:07
Electronic mailing listModule (mathematics)Insertion lossSocial classSpacetimeCovering spaceLevel (video gaming)Meta elementLecture/Conference
15:39
Order (biology)Attribute grammarSocial classMeta elementElectronic mailing listObject (grammar)Level (video gaming)Social classObject (grammar)GUI widgetType theoryMeta elementComputer animationLecture/Conference
16:16
Attribute grammarOrder (biology)Meta elementSocial classOpen setObject (grammar)SpacetimeObject (grammar)Type theorySinc functionSocial classLattice (order)Meta elementGUI widgetComputer animation
16:57
Social classOrder (biology)Meta elementAttribute grammarSpacetimeObject (grammar)GUI widgetSlide ruleSocial classCodeAttribute grammarMeta elementElectronic mailing listCASE <Informatik>NamespaceOrder (biology)IterationLoop (music)Instance (computer science)Lecture/ConferenceComputer animation
18:01
Pairwise comparisonMeta elementSocial classOpen setWindowCuboidAttribute grammarOrder (biology)SpacetimeObject (grammar)Declarative programmingInstance (computer science)NamespaceSocial classGroup actionCASE <Informatik>Attribute grammarComputer animation
18:32
Order (biology)Meta elementSocial classAttribute grammarObject (grammar)SpacetimeCuboidWindowMountain passSocial classInstance (computer science)BitRight angleMeta elementCodeSlide ruleLecture/ConferenceComputer animation
19:29
Attribute grammarOrder (biology)Social classOpen setCuboidMountain passWindowGUI widgetSystem callCategory of beingMeta elementResultantInheritance (object-oriented programming)Social classMultiplication signGUI widgetSource codeCodeComplex (psychology)Attribute grammarWater vaporElectronic mailing listCategory of beingSet (mathematics)Lecture/ConferenceComputer animation
20:21
CASE <Informatik>Set (mathematics)Standard deviationGUI widgetCategory of beingWindowDifferent (Kate Ryan album)CodeLecture/Conference
20:53
GUI widgetSystem callMeta elementSocial classCategory of beingCategory of beingCodeStandard deviationMassDeclarative programmingInstance (computer science)Process (computing)Data dictionaryGUI widgetSocial classComputer animation
21:26
GUI widgetSystem callSocial classCategory of beingMeta elementDefault (computer science)SpacetimeKey (cryptography)Message passingNamespaceCategory of beingLecture/ConferenceComputer animation
22:27
Default (computer science)SpacetimeKey (cryptography)Social classMeta elementGUI widgetSystem callCategory of beingSocial classAttribute grammarDefault (computer science)Boundary value problemCategory of beingCASE <Informatik>Sheaf (mathematics)GUI widgetLecture/ConferenceComputer animation
23:48
Meta elementSocial classGUI widgetOpen setSpacetimeDefault (computer science)Key (cryptography)Entire functionCASE <Informatik>Category of beingView (database)Social classAttribute grammarAtomic numberDefault (computer science)Instance (computer science)Lecture/ConferenceComputer animation
24:45
Social classGUI widgetDefault (computer science)Category of beingSocial classAttribute grammarBitRight angleComputer animation
25:19
Social classGUI widgetDefault (computer science)Attribute grammarElectronic mailing listData typeProper mapReverse engineeringInstance (computer science)String (computer science)Formal grammarLevel (video gaming)Execution unitInheritance (object-oriented programming)Order (biology)Attribute grammarLecture/ConferenceComputer animation
26:06
Attribute grammarElectronic mailing listSocial classData typeProper mapReverse engineeringSocial classMessage passingWater vaporCASE <Informatik>Reverse engineeringQuicksortLecture/ConferenceComputer animation
27:03
Electronic mailing listAttribute grammarSocial classData typeProper mapReverse engineeringGUI widgetNetwork topologyProcess (computing)Local GroupOpen setMeta elementWindows RegistryInheritance (object-oriented programming)Object (grammar)WindowAttribute grammarOrder (biology)Social classInheritance (object-oriented programming)Group actionStress (mechanics)Descriptive statisticsCodeGUI widgetElectronic mailing listInternet forumEuler anglesBitRight angleGreatest elementSinc functionMeta elementControl flowUniform resource locatorKlassengruppeComputer animation
30:18
Social classMeta elementData typeObject (grammar)Open setWeb pageSign (mathematics)Programming languageCodeCodeInheritance (object-oriented programming)Meta elementSocial classSource codeNamespaceLevel (video gaming)Database normalizationType theoryOffice suiteHierarchyMultiplicationGeometryBitIntegerObject (grammar)Computer animation
31:56
Social classProgramming languageCodeMeta elementBitSocial classObject (grammar)CodeLecture/ConferenceComputer animation
32:27
Social classProgramming languageCodeOpen setMeta elementMulti-agent systemMereologyBitCodeRevision controlWordLecture/ConferenceComputer animation
32:58
CodeSlide ruleOpen setCode2 (number)Meta elementSocial classAddress spaceSheaf (mathematics)Lecture/ConferenceComputer animation
33:29
ArmBitError messageSoftware design patternParameter (computer programming)Social classData conversionMixed realityMeta elementMultiplication
34:21
Parameter (computer programming)Software developerLecture/Conference
34:57
Level (video gaming)Social classArithmetic meanBitDifferent (Kate Ryan album)AreaCodeLecture/Conference
35:33
NP-hardCodePresentation of a groupQuicksortMeta elementSocial classLecture/Conference
36:03
Goodness of fitSocial classCodePresentation of a groupGraphical user interfaceMeta elementSource codeInstance (computer science)BitLecture/Conference
37:25
Network topologyGUI widgetSocial classProcess (computing)Local GroupGroup actionSocial classComputer animation
37:55
Object (grammar)Physical systemDefault (computer science)QuicksortOpen sourceDeclarative programmingWritingLecture/Conference
38:31
Physical systemCodeBitOpen sourceOnline helpLecture/ConferenceMeeting/Interview
39:01
Unit testingDataflowCodeImplementationLecture/Conference
Transcript: English(auto-generated)
00:00
Next talk up, Anders Hemmerkist is going to be telling you about using metaclasses to make a declarative GUI and then it's time for lunch. There will be questions at the end. Alright, hello everyone. As she said, I will be talking about using metaclasses for making a declarative...
00:26
It's been sitting here for too long. There we are. Making a declarative GUI implementation. I will also be telling you about metaclasses. It's sort of an inspirational talk for you to use metaclasses on your own.
00:45
The work on the background that inspired me to do this talk, I did together with my colleagues Henrik Bora and Mikkel Schoenenweg. First, a bit about me. I motivate my five-star Python rating by having been at it since Python 1.4.
01:07
I've been working at OpenEnd since 2001 and I've been consulting at Autolabel where we did this work since 2014. And I do all kinds of stuff because we're small companies so I get to do everything.
01:24
To start with, does everyone know what a metaclass is? Okay, about half of you. I can tell you that we've all used them. If you've used the class keyword, you've used the built-in metaclass type.
01:54
The other things we will be talking about is a bit of GTK which is the GUI library we used.
02:15
And of course I need to tell you why we all did this. Autolabel makes these cool labeling printers.
02:23
You have the printer printing out the label and it has an arm that sticks it onto the box. It's time to revise the software and the software running, you see the display here, that's all Python GTK interface. The one that's in this picture is running Python 2.5 and GTK 2 and we're upgrading it to 2.7 and GTK 3.
02:49
And this is what the new user interface will look like once it's done. So we wanted a nice way of expressing the layout.
03:09
As I said, the legacy application is running Python 2, well both of them are running Python 2 and we had GTK 2. We decided in this process to upgrade to GTK 3, mostly using the compatibility layer but trying to move on to the proper GTK 3.
03:42
But this is sort of the syntax that I dreamed up. This is where we wanted to go with the layout. If I quickly go back to the, you see the hierarchical, you have the sort of major groups on the left and as you go across you go deeper and deeper in the type hierarchy.
04:04
Which is, I mean, that's how GUIs are built. You start with the window and then you have the, dividing up the window in different parts and you have different widgets in there. So this, I have some code that you can download and play with and the
04:25
code on the left will actually produce the little window you see up on the right. And just for comparison, this is what it would look like in the standard GTK 3 syntax and I had to take out all the white space to make the code fit on the slide.
04:45
But for the first part, I will teach you about meta classes and as I'm sure you've heard many times, meta classes are all wizard level stuff.
05:01
So once the talk is done, you'll all be wizards. The meta class, that's the class of the class. As I said, the built-in meta class that every class in Python uses is type.
05:25
And if you want to use your own meta class, in Python 2 you use dunder meta class, in Python 3 you add a meta class as a keyword argument on bar. The code examples are Python 2, I will try to mention how to do it in Python 3 when there's a difference.
05:48
The example code that you can download if you run it through Python 2 to 3, it will run fine on Python 3. There's a bit clearer illustration of what the meta class is. Everyone knows what an instance is and what a class is, I hope.
06:10
So the relationship between the meta class and the class is exactly the same as between the class and the instance.
06:20
And that of course leads to questions, can you have meta meta classes? And yes, you can. I haven't figured out a reason why you would want to use a meta meta class on the meta class, but you can go on forever. If you specify a meta class in your meta class definition, it will work just as well.
06:48
But as I said, I haven't been able to figure out a use case for it, but if you do, please tell me. So, the methods that you will actually be using if you write your own meta class is the dunder new, which is the constructor.
07:08
It returns the object that you're instantiating. You don't actually have to return an instance of the class that you're in. You can return whatever you want.
07:25
If you return 42, instantiating the class will give you the integer 42. Try not to do that, it can be very confusing. Dunder init of course, once you have your meta class instantiated, that is once you have
07:45
your actual class object, your dunder init will be called and you can do stuff there. In Python 3, there is a method that would have been useful for us in implementing this, this dunder prepare, which
08:02
is called before the class declaration is parsed to return the dict-like object that will be used to populate the namespace. So, if you don't want to use a standard Python dict in Python 3, you can. You can dream up any dict-like object.
08:25
So, for instance, if you need ordering, which we need, you could return an order dict from the dunder prepare. Then also, the difference here with Python 3 is that you see the KWRX on the dunder prepare.
08:42
You have the keyword arguments for new and int also, and they come from the class inheritance list. If you add keyword arguments there, they will get passed into the constructor methods,
09:02
which can be useful in some cases if you need to customize your meta class. Right. So, if you add other methods on your meta class, which you may want to do because you don't want to have 300 lines of new, those methods will be visible on the class, but not on the instances of the class.
09:30
Which, it's good to know, because you'd be less confused about why can I call the foo method on the class, but not on the instance.
09:46
Where did it go? Ah, it was on the meta class. So, one thing I wanted to sort of take back from this about the meta classes. The class
10:07
declaration syntax in Python, you see on top, it's really only syntactic sugar for instantiating the meta class. So, the top code and the bottom code, the result, the foo class, it's exactly
10:23
the same. Once you've run the code, you cannot tell the difference between these two. So, try to remember that, that you can use the class declaration syntax to instantiate a class essentially, the meta class that is.
10:50
That gives you lots of power to use the class syntax for things that, well, there's classes, but not really
11:01
the standard Python classes, which is sort of the idea that I used to dream up this GUI declaration syntax. And just for comparison again, just not all of it, but the top is the declarative syntax that
11:28
we'll be looking at how we did, and the bottom is what it would look like if we hadn't. And I just have a little pause here to see if you're following along. Are
11:41
there any questions on the meta classes? Or should we continue to look at the code? So, right. As I said, the first problem we ran into was that in a standard class, you just get the dict with all the attributes in some random order.
12:10
And when you're declaring a GUI, obviously you want to be sure that whatever you put on top, the first spot in your window, it shouldn't randomly appear somewhere in the middle.
12:23
You want the order well-defined. And since we were using Python 2, we couldn't use the dunder prepare. So this was really the, I'd say it was the hardest bit of making this work, figuring out how to do this.
12:45
Not that it was very hard, but then I've been at this for a bit, so I might not be the one who should be judging how hard it was. What I did was that as long as the contained or the attributes in the class were
13:13
also instances of our meta class, I would be able to sort of detect when they were created.
13:25
And this, for our application, since everything was going to be a GTK widget, this was no problem. Everything was going to be instances of our meta class. So whenever you had the class on the inside, I should actually back up a bit to this slide.
13:53
The way, if you look at the top half, the way that the meta classes get instantiated is that it will instantiate from the inside out because label is going to be an attribute in the group class.
14:10
So the label would have to be created first in order to be able to be placed in the namespace of group and so on up to the top.
14:21
So therefore, when label is created, I will remember that now label was created. And then when we get to group, okay, let's see what has been created recently.
14:42
And I'll go through the list of the recently created classes and the order they were created in. And I'll say, ah, label was created recently. Is label in my namespace? Yes, it is. Okay, so that one must have been first.
15:12
And then I, of course, once I found them, I will remove them from this list. And it will waste a little space. Well, not really because you will be keeping the classes around anyway.
15:24
But you'll have the list of a few of the top level classes still remaining because there is no meta class for the module basically to clean up this list. But that's small enough that it doesn't matter.
15:43
And I'll take this opportunity to have my first GTK quirk that I ran into also. And that was that the G object also has a meta class. And it took, I didn't realize this at first and I was really confused and why can I not inherit the GTK widgets in my widgets.
16:07
And it turns out it was because the G object also had a meta class and they were colliding. But once I inherited it, the G object meta class, as you know, type is both, it's a bit of magic built in.
16:31
Because if you just use type as is, it's the base meta class. But if you call it with an object, it will return its class.
16:45
And since G object is already a class, it will be the meta class. So yes, this is our meta class for our base widgets.
17:05
And you see here when, actually I think I missed the code where I actually add, maybe that's on the next slide, we'll see.
17:21
So here anyway, these attributes, class attributes or meta class attribute, it would be in this case, that will be populated with the list of classes as they're instantiated. And then I will go through it and look for whatever is in my namespace, append it to my local list of ordered attributes and then remove them.
17:48
And as I'm sure most of you know, you cannot remove stuff from a list while you're iterating over it in a for loop because then you will miss stuff. Namespace is the dict that is created, let's see, for instance if you look at the top,
18:12
the namespace is the dict that is created from the attributes in the class declaration. So in the case of top here, namespace will have title, hello world, and it will have group which will be the instance of the group class.
18:26
So I look through there for instance of classes really, instances of the meta class. It's a bit confusing with the meta class because you have meta class instances which are classes.
18:46
So the terminology gets a bit confusing. And then at the end I will of course instantiate, calling the super class dunder new which will instantiate the actual class.
19:05
I realize here I forgot this code is actually wrong. On the slide, the code that is downloadable is slightly different so that one is right. The return from the dunder new I should of course have saved someplace because that's the actual class that needs to be passed on up.
19:31
So you've seen this a couple of times but using that meta class you just saw, assuming that you actually return the result from the super dunder new,
19:44
this code will get you an attributes ordered attribute on the top class which will be the ordered list of the inside classes. So that's our, now we solved our first problem, now we can actually order stuff in our classes.
20:08
The next one is we wanted to do of course, we wanted to be able to set properties on the GTK widgets. And also on our own complex widgets, we have special widgets that deal with settings and they know all kinds of magic stuff.
20:33
So in the case of window, title there should obviously set the title of the window. And in GTK, the title of the window is a property which is not a standard python property but
20:49
it's a little bit different and so I need to add some code to set it in the proper way. And also I wanted to be able to, if our code has a standard python property, I wanted to be able to set that property in the declaration.
21:12
So for instance, normally if foo widget has a property, foo, setting foo in a subclass like this would overwrite the
21:25
property and you would lose whatever setter and getter methods you had and just have a standard 42 in the class dictionary. But with some magic you can make this syntax instead called the setter.
21:51
One way I thought about maybe doing this was to use a setter on the metaclass because then maybe it would
22:02
be called once you set the 42 and you can do stuff in the metaclass, in the property on the metaclass. But it turns out that the namespace, the initial namespace doesn't bother about looking for properties, so that didn't work.
22:28
So basically what I do is I put an attribute on the class under defaults which I will populate with any...
22:47
First, in the metaclass when you write your, this is when you have your, in this example when you
23:04
create your foo widget class, it will look through your attributes and see are any of these attributes properties. Either in the case of the Python property it will look for a dunder set on the attribute.
23:28
So if foo in that case had been a property, the property would have a dunder set to, that would get called whenever you change the attribute.
23:46
Properties are subject enough for an entire other talk because they're really useful too but I shouldn't get into them too much here. And in the case of the GTK properties there is a props attribute on the GTK class so I look for if the attribute you're trying to set is in that one.
24:08
And if it is I will take the attribute you're trying to set and move it to this dunder defaults dictionary.
24:32
And then the cooperation from the base widget, this is a normal class, this is not the metaclass.
24:40
When you instantiate that I look through this dunder defaults which is in the class and if there is anything in there I will set that or that. And since I removed the attribute from the class it will now call the property setter method.
25:04
A bit roundabout way but it works quite nicely. And of course if it was a GTK property I will call the setter on the props attribute instead. Right. I should mention the dunder MRO. How many know what dunder MRO is?
25:38
Okay, it's about half. I want to mention it because I used it obviously.
25:47
It's the order that you should look through your base classes when you're looking for an attribute or a method.
26:01
So for instance here I've put up the dunder MRO of strings just as an example. So you're supposed to start with the first one and go through them and once you come to the class that has the method you're looking for you should call that.
26:21
And normally you do that using super if you are involved at all. Usually if you just say foo.bar python will look for bar for you. But in this case I needed to sort of look through them myself and it turned
26:43
out in all my use cases it was much easier to just overwrite what I found. Then it was to look and see is it here? No. Is it here? No. Is it here? So I did. I walked in the reverse and just made sure the top one won in the end.
27:03
There's a really, I wouldn't say complicated, but it's a really long description of how the MRO is calculated at this URL at the bottom if you're interested.
27:23
And then of course the next order of business is instantiating the widgets. You get your actual window and all the actual widgets inside your window. If you just do nothing special instantiating top will get you a top and it will have attributes in it.
27:47
But that will still be the class group which is not the actual vbox that you want. The simple way to do this is of course in the base class when you
28:01
instantiate top have it in turn go through its attributes and instantiate whatever is there. And then of course it needs to, since it's widgets it obviously needs to put them somewhere also but the base
28:22
class can't know where to put them so that each individual widget will have to figure out where to put them. And so that code looks like this and again I'm walking backwards through the MRO to find all the widgets because I
28:43
don't actually know if I needed to do this but I wanted to instantiate them in the same order that they were listed. And then I replaced or I set the attributes order list on the class with the instantiated attributes instead of the classes because I felt that
29:09
if I needed the classes I could go through the class and made stuff look a little bit nicer and I didn't have to invent new names.
29:20
And then for the last order of business we have mixins. We wanted to do mixins. GTK doesn't allow multiple inheritance. I hope you can see the problem here.
29:43
Python doesn't know that GTK doesn't allow mixins so it will happily let you try. Things break in strange and mysterious ways sometimes. But it turns out that if you do nasty things with the GTK meta class you can sort of work around the fact that you can't subclass GTK classes.
30:16
And I will just show you the code. So basically if we find in the meta class if we find that we have more than one base class this is multiple inheritance.
30:30
We may have to do something. The dunder G type is set on all G object classes. So if you have a dunder G type you know this is a GTK class.
30:41
I'm getting to dangerous territories here. And if I do it turns out that I want to put an extra layer in between. I don't know why this works but it helps for certain bugs.
31:00
Or well, features I guess in GTK. So I quickly invent one more level of class hierarchy to sort of bring in all my base classes into one. And then I can add my stuff to look through here and find stuff and put it all into my namespace and eventually instantiate mine.
31:31
I don't know why it works but it does. Yes.
31:45
Finally we're at the end. So I hope you've learned a bit more about what meta classes are and what they can be used for. It is obviously how your class object is instantiated.
32:03
You can go and customize it and do weird shit. And I also hope you've been inspired a bit to try and abuse Python into doing what you want and giving you a nice syntax for your problems.
32:23
Not everything that you have is beautiful code but hopefully you can make it a little bit more beautiful. I have code for you to play with. It's a little bit bigger than what I've shown here. It will run on Python 2 as it is.
32:43
If you pass it through Python 2 to 3 it will run on Python 3. I have tested both versions so it should work. Famous last words, you know. But there you go. You're hopefully now all wizards.
33:04
And now I should just put up the URL for where you find the code. Hi. So first of all, thank you very much for the talk. I think it's the first talk about meta classes so kudos to that. It's actually my second talk about meta classes but not this year.
33:24
At the conference. Yeah. Okay, so I think we all agree that meta classes are one of the best features in Python. And so I had a bit of a problem with meta classes because in some design patterns you would want to use multiple meta classes for one class.
33:50
And the magic method __metaclass takes only one argument. And the solution for this is a bit cumbersome, namely you have to create
34:04
an abstract class that takes mixins as meta classes and throw that into your class. And I was wondering if you have like a better solution.
34:20
No, not really. I suppose that for some things in Python 3 you could use the keyword arguments but I'm not sure. It depends a bit. But for Python 2, no. Alright, next question. Anyone else?
34:45
Aren't you afraid if a new developer comes to your team and he has like two stars or three stars on his badge, he won't be able to follow what you've been written? Actually not. Because once you look at it, yes, you have to grasp that you have one more level of class instantiation.
35:07
But once you pass that, it's not really that difficult. Have you ever written a meta class?
35:21
Well, the only place I actually actively use them is in Django. But that's a bit different story I guess. I hope you take a look at the example code I have here so you can hopefully see that it's not so much magic.
35:44
I think mostly what's lacking is telling people and documenting how to use them, not so much the difficulty. But as always, good documentation makes hard problems simple.
36:02
Hi, thanks for this presentation. I was not aware of meta classes and I tried to solve sort of the same problem with GUIs in Python that you did without meta classes and it looks quite ugly. I was just wondering, when you lint your code, do you get any problems with having so many nested classes? No. I mean, there is one small problem with having the nested classes and that is that it's hard to find...
36:33
When you're in one of the nested classes, you cannot easily get...
36:48
If you're in the dunder new or dunder init method of one of the nested classes, it's hard to find its actual class instance.
37:05
So, because the class outside of it hasn't been completely initialized yet, but that's the only problem with the nested classes. I can do this just to make it a bit clearer what I'm talking about here.
37:26
When you're in the dunder title, sorry, the dunder init of title, group and top don't exist yet, so you can't say top.group.title if you need to call, for instance, super.
37:43
But other than that, it's no problem. Thank you very much. I just wanted to say that I think you should retitle your talk to, I never met a class I didn't like. Okay.
38:00
Thank you. So, hey, it looks like what you've done is taken GTK objects, which are pretty horrible to use and initialize, and you've made a much nicer API declarative syntax for writing it. So, I guess if I was starting to write GTK GUI code, I would rather use your system than the default one.
38:21
So, have you thought about open sourcing your package and making a sort of GTK zero and contributing that back and making the world better? I have. What we're using right now is a bit too deep in our system with all kinds of strange stuff which doesn't really apply to a generic system.
38:46
I hope that the code that I've put up here can grow into something like that. I'd be happy to try and sort of help that effort along. And the code here is, of course, open source.
39:09
One more question. Is it hard to unit test the code you write like this? No. We have unit tests for pretty much everything, so it's not. And there is unit tests with the example for the implementation too.
39:27
Alright, is that us done? Brilliant. Thank you very much.