> For the complete documentation index, see [llms.txt](https://combo-of-rl-and-trading.gitbook.io/rl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://combo-of-rl-and-trading.gitbook.io/rl/foundations-of-rl-with-applications-in-finance/abstraction-immutability-dataclasses-type-checking.md).

# Abstraction,Immutability,'dataclasses'，Type Checking

In the realm of programming and design, abstraction is an integral notion. It's a kind of "compound thinking," a singular concept capable of unifying multiple independent ideas. This tool allows us to overcome our working memory limitations, which allow us to process around seven independent concepts at a time, thus enabling us to handle more complex problems with clarity.

The concept of abstraction is especially crucial in Python programming. Python offers a `dataclasses` decorator that helps us automatically generate certain methods such as `__init__`, `__repr__`, and `__eq__`. This significantly simplifies class definition and enables us to more easily define and utilize complex data structures. Here is an example of a Die class definition:

```python
from dataclasses import dataclass

@dataclass
class Die:
    sides: int

    def sample(self):
        return random.randint(1, self.sides)
```

Often, after creating an object, we don't wish for its attributes to change during its lifespan. For instance, if an object's attribute is modified somewhere in the program, it could result in errors when the object is used elsewhere, making error tracking incredibly difficult.

To prevent this, we can use the `frozen=True` feature of `dataclasses`, which prevents an object's attributes from being modified after it has been created. This means that if we attempt to alter an object's attributes, Python will throw an error.

```python
@dataclass(frozen=True)
class Die(Distribution):
    sides: int
    ...
```

In addition, `dataclasses` also provides a `replace` function, which allows us to change some attributes and create a new object.

```python
import dataclasses

d6 = Die(6)
d20 = dataclasses.replace(d6, sides=20)
```

Type checking is another vital element in Python programming. In our Die example, we have used type annotations to indicate that the `sides` attribute must be of type `int`. Similarly, we know that the outcome of a die roll should also be an `int`. We can annotate the return type of this function by adding `-> int` after `def sample(...)`:

```python
@dataclass(frozen=True)
class Die(Distribution):
    sides: int
    def sample(self) -> int:
        return random.randint(1, self.sides)
```

Moreover, Python has numerous external tools, such as Integrated Development Environments (IDEs) and Type Checkers, that can detect type mismatches without running the code. This method of finding type mismatches without running the code is known as static type checking. Python has several external type checkers at our disposal:

* Mypy
* Pyright
* Pytype
* Pyre

In addition, PyCharm IDE also has a built-in proprietary type checker.

In conclusion, this is the foundational knowledge about abstraction, immutability, and type checking in programming. Through the concept of abstraction, we can amalgamate complex notions to tackle intricate problems. Meanwhile, with the aid of immutability and type checking, we are able to write safer and more robust code.
