 Hi everyone. So our next talk is under and under Python secret functions by checking. I mean the title looks pretty exciting and yeah, the stage is yours now. Thank you so much and hello everybody. I'm Czech and today I got to talk about some Python secret for you. So sit back and buckle up and we got to just dive into what's Python hiding behind the scene for us. So first of all I think I would just do a brief introduction of myself. I'm Czech and I love open source project. I have been creating some projects in PaaS. I've been involving some projects in the PaaS. I of course have contributed to different projects. Some of them you may have already heard about like pandas or they should tell and projects like that. But now I'm very lucky to be working full-time for a open-source graph database at TermsDB. So if you're interested in like graph database that can do git kind of things then talk to me afterwards or you will see my contact detail at the end of the talk as well. But I'm not going to talk too much about this because this talk is not about graph database. Next thing that I want to tell you about me is that I organize a lot of different events for the community. There will be a PiData global conference in November coming up and also there will be another conference in December. So both of them will be online. You can join for easily by sitting at home just like now. And also I stream on Twitch. So if you want some more Python content, if you want a little bit more of me, you can follow me there and watch me weekly. Also there's another thing that we organized with PiDataGlobal is a humble data workshop. What does it mean is that it's a Python data science workshop for beginner. It's free. All you need is to get a ticket for PiData global which it's very affordable. The minimum that you need to donate is 10 USD. So it's like, yeah, I think it's a very cheap compared to the previous conference that I've been to at PiData. But this workshop doesn't have any course on top and it's meant for beginners. So if you know anybody or if you want to learn some data science with Python then you can go to our website and find it out. So let's start this talk and I'm going to talk about Python internal functions. And this talk will mainly be shown in a Jupyter Notebook. So it's got to be live. And so yeah, so this is the Jupyter Notebook. I know it's a little bit small. So let me zoom in a little bit so you can see it a little bit better. I hope this is okay for you. Maybe I can zoom in one more time just to make it easier for everybody. Okay, I hope that you can see it all right. And if not, maybe the host can kind of give me a shout. Okay, so this is a Jupyter Notebook. I hope you know like this just let you do some Python thing with it. And so you can see here if you have done it in the past that I have written a class in Python. And if you write a class, then usually the first thing that you would do is to write a DunderInit function. So okay, so what is Dunder? Dunder is something like this. I don't know whether you can see my highlight here. So before the init, so it starts with two underscore here. So two of them. And then so it's called Dunder because it's double underscores. I think someone very smart come up with this name. I think is a brilliant name. So Dunder. It sounds funny as well. So DunderInit function is something that like a lot of Pythonistas kind of like in the blood, they just like, okay, whatever they write a class first thing. Df DunderInit self. Okay, so again, like for all these methods, you see the first thing that I passed into the method of function depends on how you look at it. Because some people study data. Some people study computer science, they will be like always a method because it's a find a function for class. I don't really care about names. So bear with me. So yeah, the first thing that you pass in itself. So this means that you pass in the object, the instance of this class itself here in this functional method. So what is an instance of a class? So when you create, so when you have a class, you can create an instance of a class. And when you create an instance of a class, this init will fire, it will just get executed. So you can, with init, you can do some like kind of initial settings with this class instances. You'll see how it worked later because I put the print here. So you see whenever I call this init, DunderInit function, you would see this got print out. So I just put a lot of print here just to show you what is going on inside. Okay, so after that, look at here down, down here, I have my print. So my print is just like your normal method, right? I think you have already done it before. So it's just like anything here in this like kind of, you know, bind it to functional method that you pass itself, and then you can pass in any parameters that you want your user to pass in. So here you write a function, usually as a good practice, you would write a doc string here. I will show you why you would like to write a doc string instead of a comment afterwards as well. There's a benefit of that. So now this function is very, just very simple, taking the user's message, it will just print it up. Okay. And but in my doc string, as a good practice, I always tell people what will be the parameter, what are you expecting from a user, and of course explain what it does. By the way, this doc string is called a num pile style doc string. So if you want to learn a little bit more about how to write doc strings and different style and all this, come to join us in the doc sprint, I would actually have time to explain to you a little bit more about doc strings. But again, I won't dive into the detail here. So after this two thing, right, that we are familiar with that under indeed and my print, well, we have something that is slightly different. We have a method or function that's the name start with an underscore. So yeah, is well, what does it mean? Like, why do you start with an underscore? It looks a little bit funny. Well, because this is an internal function, it's just indicate that Oh, this function is not meant for the user to call it it meant for the developers to use it within maybe doing some kind of internal operation within this instance class is supposed to be, you know, providing itself some kind of functionality because, well, we all have experienced that sometimes the code get really big and we want to, you know, put a section of the code as a function. So we can reuse them. So it's more organized. So your code look a little bit better. So this is the actually the purpose of this underscore. My phone is such so it's providing for the other external method that okay, I have some helper function here that's sitting at the back seats that is not supposed to be you know, called by the user. Of course, you can still write a doc string, but it's less important here because it's supposed to only help the developers. Of course, you can still write it, it will be helpful for your fellow developers, but it's not super important like the my print. Okay. So I also if you call it, it would just print out that okay, this is my function, you shouldn't call it. And then there's something that is similar, but slightly different because it started to underscores of thunder instead of underscore. So I just print out this is a secret function, you should really not call it you will see why in a bit. So okay, I have planted a lot of seed of like what is happening here. So let's have a look. So of course, I can create an instance. But before that, because it should be the notebook, I have to run the first cell first. Otherwise, it's not registered in the kernel. So yeah, I have created an instance. So my object is an instance of my class. And I've created an instance. Yeah, so straightforward. And of course, I can print out a message. Yeah, this is my message. This is something that you may have seen before. It's not too unfamiliar. So here, another thing. So I talk about why a doc string is a good idea is that if you're using Jupyter notebook, actually, or actually, or in your Python interface, you could I think you may be able to do that. I haven't tried that though. But in Jupyter notebook, you can do question mark and then put in, you know, my print, if it's a standalone function, you can call my print. But because it's part of my object, I would just my object dot my print. And you will see that what's going on here, there is something that is pop up. This is kind of like an internal dictionary that you have written for your user. So even if they are less, they're coding on the plane, I don't know why. But you know, if they don't have internet access, they can still look at this documentation that you have put in in the doc string. So it's very handy for your user, especially, you know, you shouldn't be expecting everybody can Google anything at any time, right? Because they have bad internet connections. So this is really, really handy. So especially when you're using pandas, you can do that as well, you can just like pd.read underscore CSV, you can put a question mark in front and you will see what you should put in when you're reading a CSV. So that's one thing I can close it as well. So go back to normal. And okay, so now let's call my fun. Okay, so of course, the name is start with an underscore, I put it there. And I can still call it. It just say that oh, yeah, you shouldn't call it because I put a print stare and oops, a little bit like shaming here from the developer, which is myself. Okay, so another thing. So okay, I've called my phone I've successfully called your internal function. Can I call your secret function? Well, I call this done the function a secret function. So it cannot is a secret function. So yeah, so it's just, I just get an error from Python saying like, Oh, it is, there's no attribute secret function, something's wrong. So what's what's going on? Where is this secret function? So let me introduce you with a Python magic. It's not magic. It's just how Python work is this DIY built in function that you can call on any instance of the class or actually anything because in Python, anything is like even a number is an object. So you can have a DIY object, you know, like whatever that it is, you can put a DIY string there is it will still work. I think, see if I can show that. So this is just a lip. I didn't plan that. But if you say, Hello, here that you can still put the out in anything a string or a number and put the one there you use these still see a bunch of things. But I want to see what's inside my object. So I put the L my object. And you see here, I have my phone, which is, well, that's why we can call my phone is because this is a part of the instance is bind. This is a function that spine to the instance. Okay, and my print as well. There are other things. These are all like, it looks like the unit thing right start with a thunder and with a thunder this are all default attributes that spine to this object. So, for example, as the hour just means that you could change it into a string representation. A dog for a dog string. So the in it is here as well. So these are all the things that we a little bit familiar with some of them we really use so we junction of what they do. That's fine. So you see here, this is a very strange attribute here. So underscore my class done the secret function. This look familiar, but yet is not something that we have created, right? So let's have a look. So let's run this weird attribute. So spoiler. Actually, this is a binder function. So again, you can call it like this. Yeah, this is actually our secret function. Python actually renamed your secret function something else. So it kind of stopped people from, you know, maybe go to GitHub and looking at your code and then see oh, there's a secret function and I can just call it. No, people can maybe do that with your internal function with my fun, but not this secret function. So this is a little trick that Python do to just to make this secret function a little bit more secure. So people can't just directly call it by accident. So this is very neat. You can hide something with your class that really, really like stop people from calling it. You can still call it with your, for example, if you're my, if my fun is calling a secret function, for example, here, if a secret phone is calling self dot sorry, it's the other way around. So it should be my phone is calling, let's say self dot secret. Sorry, I just copy and paste. I'm so lazy. I'll just copy and paste here. Can I call a secret function in my phone? Yes, you can. Let me just do this again. And now if I call my phone, you see that yeah, it will call secret function without problem. We can just call it like this. But in but outside you can't just call it like here. You still doesn't work. It just work in my phone. So yeah, so it just locked the secret function to be only used internally, not being able to use by the user by accident. So that's, that's fun. Shall we do something more? Sure. So this is my list. Well, it's a list that I think of, you know, if you have already have some experience with Python, this is kind of like in your 101 book that you could create a list object in Python. So what is inside a list? So have a look. And we can see all these things that you have seen before that is method that could be used with a list, you know, append an element in the list, you know, pop an element from the list, all this stuff, you know, reverse it, sort it, whatever. Also other default things that supposed to be you won't call it directly. But you know, again, now you know all the secrets so you can do that. Let's just get items. So this is quite unique for a list object or actually any sequence or object like, you know, a dictionary or a triple, they all get this get item method here. So let's play around with this one. So yeah, my list, the item, what is this is actually a function that you could call. So how about I call get item zero, give me one. So actually, it works like this. So it's the first element of the list, right? So 123 is the first element is one. And so basically, when you do this indexing thing, so the square bracket for a list or a triple and then this get item is called. So let's do something funky. I create a sequence class, which is a not a normal sequence class because I will do the same thing, you know, in it and just say, oh, I create an instance. But this time I add the get item. And this get item again, we take in an integer, but it will just return the square of the integer. It doesn't make sense, but it's fun. So I create is my sequence object. And then so this time, actually, I don't have anything in this sequence, right? Remember, I just need and just print out create an instance. I didn't store anything or, you know, it's just, it's not like a list or triple or anything. So but I can still use this square bracket. And it will give me the square of three, which is nine, or square of 10, which is 100. Yeah, this is funky. So for my list, which is a normal list, you can have length, right? So 123, the length is three. How about my sequence? Well, I don't have it. It will give me an error because I this is an artificial thing, right? I created it doesn't have the length thing there. If you run a DI out, then you can see L. So yeah, it's not here. So you'll be able to see it here if I have it. So no, what should we do? We could create it ourselves. So let's do something naughty. So the F length and and self, remember the self, this is a common mistake by beginners. Return just put 999 here. Yeah, so why not? So now I can call length. Oh, I can't because I haven't run this again. Okay, now I can do it. And it would just give me 999. Yeah, this is yeah, again, naughty and funky. Now you can see that it's here length is here added because I added it myself. And so another thing about list or triple or dictionary that is is called an iterable is because there is a method inside. I don't know what I can show it here. Maybe I can show you my list here. So what's in my list? It was able to see there's an iter here. So this iter means that whenever I call an iter function on my list, it should return something that is an iterator of my list. So you can see that. So now I have the iter for my list, which is an iterator generated from my list. And if I call next on an iterator, Oh, it's one. So what if I call it again? Oh, it's different is to what if I call it again? So three? Okay, what if I call it again? Okay, not this time. I can't call it again. It exhausted itself. So what happened is that whenever you call next, it will just give you the element of the list from the beginning to the end. And when it reaches the end, there will be a kind of an error-ish kind of thing that is called stop iteration that basically say that, okay, I have exhausted, I can't give you next anymore. So this is cool. This is kind of like a follow-up, right? Because like, for example, I have a follow-up here, I put my list in here. So 123, what happened in a follow-up behind the hood is that whenever I write something like this, which is a follow-up, what it does is that it will call the iter on my list. So it generated an iterator for my list just like what I did here. And then X will just be calling next to get the next value in the iterator in my list. So I print it out. So it will give me 123. That's something that we are all familiar with. What about this MySequence, this naughty boy here? Of course, I can't do this right now because it's not an iterator. Like, I don't have the iter, I don't have next, you know, so I can't really do this. This is not acceptable. So what magic I got to do next is that I got to, you know, have fun. I got to put in here. So what I got to do is that I will have an iter first, sorry, double underscore always, because I'm messing up with the default settings. So I would just, you know, return myself as an iterator, why not? So return self. And then because I am returning myself as an iterator. So the characteristic of an iterator is that I will have next, right? So I have to put next in here. Yep, so self. And I can return. What do you like? What number do you like? I feel like seven is lucky. So I return seven. Okay, so just return seven because it's my lucky number. Why not? Yeah, so let's try to create this funky instance again. And well, everything just work the same, right? I can still do this thing. I can still have length which return 999. And now if I look at my sequence, you would see next, it's in here. This is what I want. It turns in here as well. This is what I want. Great. And this time I can connect my sequence. It will give me seven. If I run it again, it will give me seven. Well, yeah, it keep giving me seven and it will never stop. And this is scary because, well, if I put it in a for loop, it will never stop. I don't want to do that. So let's create something that we could stop. So this time I really have to give this, I really have to give this sequence somewhere to stop. So let's take in an N when I create it. And then I will just put self.n equals to n. So I will just store this value somewhere. And also I have to store another thing that is a counter. So self.count equals to zero. So start with zero. And then when I call next, what happens is that if this counter is less than the self.n, which is the end of the sequence. And I will return seven. Okay, so I will just return seven. It's a happy happy place, you know, just return seven. Otherwise, so what should I do is to raise a stop iteration? Okay, so let's try to see if it works. I'm missing something. Yes, I am missing an end here. So this time I have to put in something as n. Let's put in three just to make it short and simple. So okay, now I can create an instance. All these still work the same. It doesn't matter what the length is, it's just returned the square of it because this is how I put it in. And the length will still say 999 because, well, because this is how I set it. But this time when I call next on my sequence, okay, and then, oh, I've spelled it wrong. Sorry, let me fix it. Live coding curse. Okay, now let's go back to normal and then come back here and run it. So next it will give me seven. So this is the first time giving me seven. Second time it give me a seven. Third time it give me a seven. And the fourth time is to give me seven. That's this is weird. This is not is supposed to be. Oh, I know why because I forgot to increase the counter. Yep, again, live coding curse is always something wrong with it. And I'm used to it. That's fine. Don't worry about me. And then I was just quickly, quickly run three times this thing. Sorry about that. It's a bit tedious now. And now, yeah, now it stopped iteration. Finally, it know how to stop. So we can now put it in a for loop. Sorry, as you hear, and oops, it's not printing anything. Oh, because I didn't give back anything, right? Oh, I know why because I have exhausted myself. So let me create instance again. Yeah, so three times the charm. So let's let's create a sequence object again. So now it's refreshed because previous previously I exhausted myself. So it would just like, okay, it reaches the stop iteration before ready before I put it in a for loop. But now I've refreshed. So it should be fine. I don't give me three sevens, which is a very lucky number. I love it. And yeah, so this is the end of the demonstration. Let's go back to the slice. And I only have a few slides to close this talk. And so what is my thought on this kind of craziness? So first of all, about the internal function and secret function is kind of like an option that you can, you can choose as a developer that whether this internal function is a client suggestions to tell you user that always this is an internal function, we are not expecting you to use it. So use it with a grain of salt and the documentation may not be full. So but you can still use it if you know what you're doing. If you have look at our code and you, you know, this is open source, right? So yeah, look at our code and decide whether you want to call it. Or if something that I really have to restrict you to use it, because this is super dangerous, you will, you will mess things up badly. So yeah, like, I think, as a Python Easter with some experience, I see most of the internal function are just single underscore not under. So I think this is because a lot of time we are writing code in open source settings. So there's some openness, there's some transparency and we trust the user that they will make their own decision, whether maybe develop, they develop some plugin for our library, then they may want to call this underscore function. So yeah, that's cool. That's something that I like. And also, Python is so flexible and yes, so powerful. You see when I mess around with the my sequence object, basically it lets you do anything. So that's why I love Python is that it's so easy for the beginners to use because it's hide all this complexity behind the scene. And so beginners can pick up Python and start using it quickly. I think all of you must have already experienced that. But yet it is so powerful that for more experienced user for advanced user, they can mess with all these internal settings. And basically, they can do anything with Python. So this is so good. And I really love it. So my take on all this stuff is that don't overlook the hidden beauty of Python. So yeah, this is the last slide of my talk. And here is my contact detail again. So if you want to know anything about this topic or anything about graph database, you could talk to me. You can basically find me on Twitter or anytime, you know, yeah. So that's it. I think I have a little bit time to take a few questions. So if, if there's any that that would be great. Sure, it was a great talk. We have a couple of questions that I'll read it out to you. First question is what is a binder function? Okay, so this is the function that I mentioned a little bit. So it's kind of an attribute of so when you create a class, you create all this like my fun, you know, my print and all this actually like they are function that is fine to an instance of a class. So these are all the functions that's bind to it, some in some other programming language, when you learn it, they call it a method of that instance of that class. So yeah, it's just different naming. But in Python, because an instance of a class can have different attributes. So it could be, you know, attribute as an object, you know, it could be a string and integer that you store like the n and account in my last example, or it could be a function, a function is also an object. So it could be bind to an instance of class. So the second question we have is how can we use the Dunder function if user can't even call it? And where can it be called? Oh, yeah. So if you remember my demonstration, so as the Dunder secret, my secret function can be called by my fun. So it could be called by the the bind function, the method of the class itself. So it could be called by its fellow method, you know, that sitting inside the same instance, but it can't be called outside. So this is why this is a secret function is only meant for internal use, not for external use. And so far, the most asked question is where can the Oh, you like the notebook? Okay, so right. So what can I do? Actually, I've given this talk before, but nobody really asked for the notebook. But what I can do is that I can put it on my GitHub repo. So you can see my GitHub handle there. So today within today, I would upload it to my GitHub repo. So if you click on my repository, you will find it, I think I would call it something called Python internal function or something like that. So yeah, just find it on my GitHub then. That was the last question. And thank you very much, it was an amazing talk. And yeah, have a good day. Yeah, thank you so much and enjoy the conference.