Do you know how to make a #Python class method act like an attribute?
You can do that by turning the method into a `property`
Learn how in this thread!
๐งต๐๐
The first step is to look at a regular #Python class.
The following `Person` class has a method called `full_name()`. To get the full name of the `Person`, you must call `full_name()`
Wouldn't it be nice if you could just use dot notation instead of calling it?
In #Python, you can turn the method into a `property` using the `@property` decorator
Once you do that, you can then use dot notation to access the `full_name()` method as if it were an instance attribute!
What if you want to set the property to a new value though? I mean, in a normal #Python class, the attributes can be set by doing something like `p.first_name = "Jane"`
If you try that with the `full_name` property you will get an `AttributeError`!
To make a property settable, you need to add a new function with a special decorator.
In this case, you have the `full_name()` decorated with `@property`
To add a setter, you need to create a SECOND `full_name()` method and decorate it with `@full_name.setter`
Let's look at another example! Here is a regular class that has a getter and setter function:
๐ get_fee()
๐ set_fee()
When you create a class with getters and setters, you kind of miss out on the power of Python because you can't use dot notation here
You can update the class to add a `property` by using the `property()` function.
The following is kind of a sneaky way to turn those two methods into a property without adding the `@property` decorator
However, in #Python, it is better to be explicit so here is the class rewrote with the `@property` applied
Now you'll be able to get and set the values using regular dot notation
The code for most of the examples here come from one of my tutorials @mousevspython
Concurrency is a hard topic. So today we're going to talk about multiprocessing in #Python
Join for me another fun mini-thread!
๐งต๐๐
The Pros of using `multiprocessing` in #Python (part 1 of 2)
๐ Processes use separate memory space
๐ Code can be more straightforward compared to threads
๐ Uses multiple CPUs / cores
๐ Avoids the Global Interpreter Lock (GIL)
The Pros of using `multiprocessing` in #Python (part 2 of 2)
๐ Child processes can be killed (unlike threads)
๐ The multiprocessing module has an interface similar to `threading.Thread`
๐ Good for CPU-bound processing (encryption, binary search, matrix multiplication)
There are a lot of "magic methods" or "dunder methods" in #Python.
I'll be talking about these for a few days, so stay tuned!
First off is `__init__()` and `__repr__()`
A magic method is a #Python class method that begins and ends with double-underscores
Most classes require you to create an `__init__()`
`__init__()` is short for initialization and initializes the instance
Sometimes, `__init__()` is called a constructor. However, I have seen it claimed that you need to combine `__new__()` with `__init__()` for it to be a true constructor
`__new__()` is used for allocating memory while `__init__()` is used for initializing the instance
When using a class in #Python, you may notice that the first argument in all the class's methods is "self"
What is up with that? Well, let's talk about it!
๐งต๐๐
First of all, "self" is a convention that refers to the instance that is created when you instantiate a class. You don't have to name it "self", but that is best practice
Here is an example where "self" is replaced with "this"
You use "self" to be able to access instance attributes across methods in a #Python class.
Here is an example where you initialize (__init__) `self.name` and then use `self.name` later on when you call the `walk()` method:
Whenever you talk about classes in #Python, you will probably see the `super()` function mentioned.
The most common way of writing `super()` in a #Python class is to write it like this:
You can also call `super()` with the class name and self passed in, but most #Python developers see that as redundant since it is the equivalent of `super().__init__()`
Today I'm going to start a series on #Python classes.
According to the Python docs: "Creating a new class creates a new type of object, allowing new instances of that type to be made. Each class instance can have attributes attached to it for maintaining its state. "
๐งต๐๐
Here is an example of a #Python class that has a single attribute: `name`
๐ `animal_1` is an instance of the `Animal()` class
๐ `animal_2` is another instance of the `Animal()` class
You can access an instance's attributes using the "." operator
A #Python class always inherits from the `object` base class. In Python 3, you do not need to specify that you inheriting from `object`
That means that the following two examples are doing the same thing: