The Magic Of Python

Creating Methods and Classes in Python: A Deeper Dive

One of the most powerful features of Python is its ability to create custom classes and methods. In this tutorial, we'll take a closer look at how to do just that.

By creating a class with an `__init__` method, you can define the attributes and properties of your class. For example, let's say we want to create a simple `Person` class. We can define it as follows:

```python

class Person:

def __init__(self, name):

self.name = name

```

This `Person` class takes in a `name` parameter when it's instantiated, and assigns that value to an instance variable called `name`. This is known as an "initializer" or "constructor", and it's where you define the attributes of your class.

Now, let's say we want to create a method within our `Person` class. We can do this by defining a new function inside our class definition:

```python

class Person:

def __init__(self, name):

self.name = name

def say_name(self):

print("Hello, my name is", self.name)

```

In this example, we've defined a method called `say_name`, which takes no parameters and prints out a message that includes the value of our `name` attribute. We can call this method on an instance of the `Person` class like so:

```python

person = Person("Tim")

person.say_name()

```

This will output "Hello, my name is Tim".

Now, let's take it to the next level. What if we want to create a method that calls another method, or one that takes parameters? We can do this by simply defining our new method with those parameters.

For example:

```python

class Person:

def __init__(self, name):

self.name = name

def say_name(self):

print("Hello, my name is", self.name)

def greet(self, other_person):

self.say_name()

other_person.say_name()

person1 = Person("Tim")

person2 = Person("John")

person1.greet(person2)

```

This will output:

```

Hello, my name is Tim

Hello, my name is John

```

As you can see, the `greet` method takes in another instance of our `Person` class and calls its `say_name` method.

Now, let's talk about the difference between using a class like this versus creating it manually. When we create a class like this:

```python

class Person:

def __init__(self, name):

self.name = name

def say_name(self):

print("Hello, my name is", self.name)

```

We can access the `name` attribute directly using dot notation, like so:

```python

person = Person("Tim")

print(person.name) # Outputs: Tim

```

But if we want to create a new class that inherits from this one, we have to do something a bit more involved.

For example:

```python

class AdvancedPerson(Person):

def __init__(self, name, age):

super().__init__(name)

self.age = age

def say_age(self):

print("I'm", self.age, "years old")

person1 = AdvancedPerson("Tim", 30)

person2 = AdvancedPerson("John", 40)

print(person1.name) # Outputs: Tim

print(person2.name) # Outputs: John

```

In this example, we've defined a new class called `AdvancedPerson` that inherits from our original `Person` class. We use the `super()` function to call the `__init__` method of the parent class and assign it the value of our `name` attribute.

Now, let's talk about how Python actually implements this kind of thing at a lower level. When we define a class like this:

```python

class Person:

def __init__(self, name):

self.name = name

def say_name(self):

print("Hello, my name is", self.name)

```

Python internally creates an object that has attributes and methods associated with it. This object is called a "type" in Python.

For example:

```python

person = Person("Tim")

print(type(person)) # Outputs:

```

As you can see, the `person` variable now holds an instance of our `Person` class, and we can use the `type()` function to get its type.

But here's where things get interesting. What if we want to create a new type that is similar to our existing `Person` type? We can do this by defining a new class that inherits from our existing type:

```python

class AdvancedPerson(Person):

pass

person1 = AdvancedPerson("Tim")

print(type(person1)) # Outputs:

```

In this example, we've defined a new class called `AdvancedPerson` that inherits from our original `Person` class. We don't need to define any additional methods or attributes for this type - it simply inherits everything from the parent class.

Now, let's talk about how Python actually implements the `__init__` method at a lower level. When we define an `__init__` method like this:

```python

class Person:

def __init__(self, name):

self.name = name

def say_name(self):

print("Hello, my name is", self.name)

```

Python internally creates a special function called `__new__` that is responsible for creating new instances of our class. The `__init__` method is then called on the newly created object to initialize its attributes.

For example:

```python

person = Person("Tim")

print(person.__class__.__name__) # Outputs: Person

def create_person(name):

return Person(name)

new_person = create_person("John")

print(new_person.__class__.__name__) # Outputs: Person

```

In this example, we've defined a new function called `create_person` that creates an instance of our `Person` class. We can use the `__class__` attribute to get the type of the newly created object.

As you can see, Python provides a powerful set of tools for creating custom classes and methods. By understanding how these concepts work at a lower level, we can create more complex and flexible software systems that are tailored to our specific needs.

"WEBVTTKind: captionsLanguage: enhello everybody and welcome to another youtube video so in today's video i'm going to be sharing with you some very advanced and interesting programming concepts in the python programming language now the point of this video is not to give you a full tutorial on all the stuff that i'm showing you but just to expose you to what you can do when you really do have a mastery or kind of expert level understanding of a language now i don't claim to be a python expert but the stuff i'm showing you here is definitely expert or advanced level features in python and obviously you don't need to understand every single aspect of python to understand this one kind of cool thing i'm going to show you here again this is not meant to be a full tutorial just to expose you to what's possible when you really have a deep understanding of a language and how you can implement some very advanced and interesting behavior that you may not have anticipated before so i'll kind of leave the intro at that but i will mention that if you're interested in this type of stuff you were able to follow along with this video i do have an expert python tutorial series that goes through more things like this in the python programming language i believe there's six videos in that series and we'll leave a link to that in the description and a card in the top right hand corner of the screen so with that said let's look at the magic of python but what is also magic is the sponsor of this video before we get started i need to thank the sponsor of this video which is sublime merch sublime merge is a git client that makes managing your code repository simple without hiding the power of git it was created by the same team that made sublime text and was designed to write a fast and simple to use tool that still provides all the powerful gate features with line by line staging powerful search and easy customization sublime merge offers a better and faster way to interact with your git repositories one of my favorite features in this tool is the sublime highlighting that allows me to quickly see the changes in commits and provides proper syntax highlighting for over 40 supported languages out of the box another useful feature is that sublime merge uses actual git and allows you to see all the commands it's running for you and even add your own custom commands now just like sublime text sublime merge is fully customizable you can change the layout theme and more sublime merge is free to evaluate with no time limits or restrictions and if you're a sublime text user already you can bundle it with the newly released sublime text 4 and save get started with sublime merge today by clicking the link in the description all right so let's go ahead and get into the video here now the first thing i'm going to mention is why i called this video the magic of python what is magic about python well in any programming language and python especially there's a lot of high level syntax and great features that you can use without having any understanding of how they actually work on the back end right and great example of of these sorry is functions like say len right this len function we just take for granted that this can give us the length of any object we have functions like int this can convert something to an entry create a new int for us we have a bunch of other functions right we have the map function we have the filter function we have a ton of things that we can just use and we can kind of take for granted we don't have to understand how they're implemented and when we use these things some magic occurs in the backend and then we get some result or some behavior and so what i'm going to do here is kind of peel back you know some of that back end code and show you what it is that's actually going on in the back end specifically when you create a class now you'll see why i'm going to show this to you in a second but i want to start by kind of introducing the concept of objects in python to everyone now i'm sure many of you are familiar with objects if you're watching this video you're probably familiar with object oriented programming but one thing you have to realize about python is that pretty much everything is an object so something like x equals one you know this is an int data type but if actually go ahead and print the type of x we can see this is from class int so what this really means is x is an instance of the class int it just happens to have the value 1. now since this is an instance of class int this means i can add other integers to it right i can say print x plus 2 and that's all good we get the value 3. and if i am actually to print the type of x plus two so if i do that you see again we get class int the result here which is three is of type in so it's an instance of the class it so these classes are kind of like blueprints that define the behavior of the different objects in python if i create another variable here and we make this equal to a string and i print the type of it well you're going to see that it is just simply going to be string now what happens though when i try to actually print say x plus y well when i do this notice we get an error it says unsupported operand types for int and string so since one of these variables is type string and the other is type ins i cannot add them together because that operation is not defined and so just keep that in mind there that these classes or these types really are blueprints defining how objects can behave in our program what methods we can use on them what operations or operators we can use with them it's a blueprint defining the behavior that's really the key thing to think about classes are just blueprints that define how objects behave and you can obviously have many objects of the same type or of the same class so now though let's create a class let's go ahead and say class we can just do a really simple class maybe like person and we'll define in a nit in here we don't need to do that say define underscore underscore in it underscore underscore and quite simply we'll just take a name right and then we'll say dot name is equal to name okay so we've created this person class this is great and we now know that we can do something like x is equal to person and then we can give it a name say like tim if we run our program no problem this works totally fine however why is it that we can write this syntax how does python actually create a new class that is a person class well one thing i want to show you here is that if i type or sorry print the type of x we get main.person so the reason it's saying main is because the module in which you run the python code in is called main so whatever module is executed its name is kind of main and then we say dot person just to kind of signify that the person class is inside of the main module that's great that's pretty straightforward i'm sure that's not confusing everyone however what happens when i look at the type of the class right so now notice i've not created an instance of this class i'll delete that i'm looking at what the type of the actual class itself is and when i do this notice we get class type now that's kind of strange because when we think of creating a class we think of creating a new type right we're creating this person type and we can create objects of type person but it turns out the classes themselves are objects that are of the type type so i understand that that's confusing but there is actually a blueprint above our object or above our class story that defines how we can create a class so just like this is a blueprint for the person objects there is actually a blueprint for creating classes just like there is a blueprint for creating functions right if i define foo maybe we take an x here and then we print x i think many of you have probably seen this before but i can print the type of foo oops and i see that this is class function so there is a blueprint that allows me to define functions and there is a blueprint that allows me to define classes now since there is this other type this type type and notice we're using this type function right here this means that this is not actually the only way that we need to create a class and i'm going to show you now kind of the advanced behavior of classes and what you can do when you understand the fact that a class is of type type so let me erase all of this and what i'm going to show you here is how i can create this exact same class without using this high level fancy syntax and the way we do this is we use something called type so what i'm going to do is create some variable let's just call this new underscore class okay and this is going to be equal to type we've used this function before but it turns out that this function can not only give you the type of something it can allow you to create a new class of type type or a new object of type type which would be a class so the three arguments that go to this function here are the following they are the class name so in this case my class name is going to be person any of the what is a base class is sorry for this class so anything this class is going to inherit from would go right inside of here and then all of the attributes on this class so attributes of a class are things like methods class methods static methods so on and so forth class variables those are all attributes of a class and so what i'm going to do here is i'm going to create a function i'm going to call this function person underscore a net what this function is going to do is take in self and it's going to say actually sorry it's going to take itself and it's going to take a name and it's going to say self.name is equal to name notice this is the same as the init function right here okay so we have this init function what i'm going to do now is create an attribute of this class which is the init method okay so i'm going to say init and then this is going to point to the person init now walk through this slowly in a minute but what i've actually just done here with new class this line right here has created this exact same person class so sorry it would be these three lines here but these three lines are equivalent to this right here and i'll show you what i mean in a second so what this is actually done is it's created a class called person it has no base classes and it has one attribute which is the init method so double underscore init double underscore and that is equal to this function right here so you can imagine this is me kind of mapping this init method to this function that we've defined and now what i can do is i can actually use this new class variable to create an object of a type person so let me actually just comment this out uh what do i want to do here oops i'm in the wrong programming language for that okay so let's just comment this out and what i'm going to do is say that x is equal to new class and then i'm going to type in the name of my person i'm going to say 10 and then i'm just going to simply go here and print and this will be x dot name okay so when i do this you're going to see that this works and this is very strange don't get me wrong what we've done is we've stored the class person in the variable new class and then we've created an object of type person which we do by initializing new class and then we've looked at the name of that person there you go now if i want to actually look at the name of this new class what i can do is i can print new underscore class dot underscore underscore name underscore underscore oops and if i do this oops new class or any one more s here you're going to see that this new class variable is actually the person class so hopefully this isn't confusing you too badly but this is how you can actually create a class using this type function and that is because again there is a blueprint above our kind of pre-built in classes here that tells you how to define a class now since that is the case since there is this blueprint we can do these very advanced things like this where we dynamically create a class we can use this type function we can make a class name we can give any parent classes and then we can give all of these attributes now let me show you how you would add a method to this class so we'll leave these lines here what i'm going to do is say define say name this is going to take in self and what this is going to do is print self.name okay so now what i'm going to do is i'm going to hook up this method here so i'm going to say ok the method say underscore name is equal to a function and this is say underscore name now what i've done is i've allowed myself to use this say name method whenever i call dot say name what that's going to do is called this function right here because i've kind of hooked them up in this way so now rather than just printing x dot name what i can do is i don't even need to say print actually i can just say x dot say underscore name and then notice it says tim so that is how you would go about creating a method now we've already seen how you can add actual attributes or properties to this class which is by simply uh creating the initialization sorry so in the initialization right i have myself i have my name and then what i could do after here is i could take other attributes as well maybe like age and i could say self dot age equals age and these are kind of the instance variables associated with the class defined in this way but the whole point of me showing this to you is that this is exactly equivalent to me doing this in this class syntax and what happens in this class syntax is the python interpreter actually goes through parses all of these methods which are really just functions inside of the class right and then uses this type function to create the class in the way in which we're manually doing it down here so here it's just kind of the you know short form syntax essentially this is the nice way the pretty way of doing things but you can go right down to kind of the the bare bones level and create the class on your own so if i wanted to make these classes equivalent then i would need to do my method say name again this would need to take self and then i would need to just print self.name and now my person class here and my person class here are the exact same so you might be asking me now why would i ever want to do that why did you just spend 10 minutes showing this to me this seems cool but it's like relatively useless i'm never going to do this now chances are you probably never will do this right this is something that's very very specific and that is not a common thing to be doing in python programming and only very very advanced people actually kind of mess with this type of stuff but the idea here is that this now allows you with this knowledge to actually implement much more advanced behavior in python and where this would lead to if i were to continue going with this explanation is something called metaclasses now i'm not going to explain metaclasses in this video because i have an entire video going through metaclasses again you can find that in the expert python tutorial series but since we now know that the class person is of type type what that means is that i can create a class that actually is a subclass of class type and use that class to create new classes so this is kind of weird but i can make a class like class create class and i can just put type here now what i'm doing is i'm actually subclassing type right i'm creating a class that inherits from type and now what i can do is i can change the behavior of the type class some of it at least i can hook into and modify and overload different behavior and i can actually change the way in which classes are created and this means that now when i want to create a new class rather than using type i would use this create class thing so if i just put a pass here and i use create class like that you're going to see that this all works the exact same because what i've done is i've created the blueprint for my class right i've said okay i'm going to have a new blueprint now it is a subclass of type so whatever type does this will do and then in here i could go in and i could change how type actually works and i can then put constraints on the modification of classes or the creation of classes and i could change how a class was actually constructed what methods are called first is the init method called first is the call method called first is the new method called first if you know what those are if you don't know what those are don't worry but it allows you to do very very advanced and interesting things so i think i'm going to leave the video at that i'm sure this last part was maybe a little bit of a brain explosion for some of you guys because this is some pretty advanced stuff let me know what you guys think of this if you want to see more advanced syntax and concepts in python do let me know i usually stay away from them just because i know a lot of you guys are beginners or intermediate programmers but if there's a demand of course i'm happy to make some more videos about this topic regardless i hope you guys enjoyed if you did make sure to leave a like subscribe to the channel and again you can check out that expert python tutorial series learn more about this stuff you\n"