# What is the new Self Type in Python 3.11?

If you have been using `Typehints` in Python, you are already aware of how we use Types in Python, although keep in mind that the Python runtime does not enforce function and variable type annotations. They can be used by third party tools such as type checkers, IDEs, linters, etc.

In the freshly released Python 3.11 (2022-10-24) also known as [PEP-664](https://peps.python.org/pep-0664/), so many features have been introduced such as faster CPython, Support for parsing TOML & `Self` Type and much more.

Let's focus on `Self` Type for this blog. `Self` Type is defined in [**PEP 673 – Self Type**](https://peps.python.org/pep-0673/)**.** But What is the use case of this `Self` type? Let's understand by an example.

```python
class Shape:
    def set_scale(self, scale: float):
        self.scale = scale
        return self

Shape().set_scale(0.5)  # => Return type should be Shape
```

As given in the above example, `set_scale` will return the `instance` itself, which will allow us to do method chaining. But how do we define the return type of `set_scale` above?

One way to denote the return type is to specify it as the current class, say, `Shape`. Using the method makes the type checker infer the type `Shape`, as expected.

```python
class Shape:
    def set_scale(self, scale: float) -> Shape:
        self.scale = scale
        return self

Shape().set_scale(0.5)  # => Return type is Shape
```

So we have got the solution, but is it really going to work if we create a subclass of `Shape` and use the `set_scale` method in that subclass? The answer is no, let's understand from the below code.

```python
class Circle(Shape):
    # Circle is a Subclass of Shape
    def set_radius(self, r: float) -> Circle:
        self.radius = r
        return self

Circle().set_scale(0.5)  # Return type is *Shape*, not Circle
Circle().set_scale(0.5).set_radius(2.7) # => Error: Shape has no attribute set_radius
```

As given in the above example, the IDE will show an error on the last line because `Circle().set_scale(0.5)` return type is `Shape` and IDE is not able to parse that we are calling `set_scale` from `Circle` not `Shape`. Hence, the new `Self` needs to be introduced. Let's understand how it works.

```python
from typing import Self  # New Self type

class Shape:
    def set_scale(self, scale: float) -> Self:
        self.scale = scale
        return self

class Circle(Shape):
    def set_radius(self, radius: float) -> Self:
        self.radius = radius
        return self

Shape().set_scale(0.5) # Return type is *Shape*
Circle().set_scale(0.5)  # Return type is *Circle*
Circle().set_scale(0.5).set_radius(2.7) # Return type is *Circle*
```

Above, the return type `Self` represents the fact that the function returns `self` (which is an `instance` of the class) and is easier to understand.

As in the above example, the type checker will correctly infer the type of `Circle().set_scale(0.5)` to be `Circle`, as expected.

This is it for today.

***Any thoughts? Write it down in the comments.***

> ***For more such crispy blogs daily, follow Dev.Junction, subscribe to our newsletter and get notified.***

## **Social Links**

* [**LinkedIn**](https://www.linkedin.com/in/mnamegaurav/)**:** [**linkedin.com/in/mnamegaurav**](http://linkedin.com/in/mnamegaurav)
    
* [**YouTube**](https://www.youtube.com/devjunction)**:** [**youtube.com/devjunction**](http://youtube.com/devjunction)
    
* [**Website**](https://gaurav.devjunction.in/)**:** [**gaurav.devjunction.in**](http://gaurav.devjunction.in)
    
* [**GitHub**](https://github.com/mnamegaurav)**:** [**github.com/mnamegaurav**](http://github.com/mnamegaurav)
    
* [**Instagram**](https://www.instagram.com/mnamegaurav/)**:** [**instagram.com/mnamegaurav**](http://instagram.com/mnamegaurav)
    
* [**Twitter**](https://twitter.com/mnamegaurav)**:** [**twitter.com/mnamegaurav**](http://twitter.com/mnamegaurav)
