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: