Type coercion or why 6 + True is 7 in Python
Tags: python, programming, tutorial
Published: 2023-10-21 17:40:16

## Type Coercion

In the landscape of programming languages, many of them have a feature called Type coercion. This means that the compiler/VM/interpreter will implicitly convert one object to another type depending on circumstances.
By default, Python does not have this feature. This lack of type coercion in certain situations can lead to unexpected results or behavior that may surprise some developers. Let's investigate these cases and circumstances to learn more about it.

## Numeric types:

### Fraction type and integer:

```python
from fractions import Fraction

print(Fraction(1,2) + 1)  # Output: Fraction(3, 2)
print(1 + Fraction(1,3))  # Output: Fraction(4, 3)
print(Fraction(1,2).__add__(1))  # Output: Fraction(3, 2)
```

Python works seamlessly with Fractions and integers. However when it comes to floats and integers:

```python
print(1 + 2.3)    # Output: 3.3
x = 1
print(x.__add__(2.3))   # Output: NotImplemented
```

Integer doesn't know how to behave with a float,
but float numbers do.

```python
x = 2.3
print(x.__add__(1))
```

In the above example, adding an integer and a float using the '+' operator works fine in Python because it automatically performs type conversion for us behind the scenes. However when we try to use 'add' method explicitly on an integer object with a float value as argument (i.e., x.__add__(2.3)), it returns 'NotImplemented', indicating that this operation is not supported by default.

### Strings

And what about object string?

```python
a = 'test'
>>> a + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
```

So is it possible to hack this kind of behaviour in python?
Yes, we can create a custom string class that allows us to add integers to it using the `__add__` dunder method. This is an example of metaprogramming in Python.
Here's an example code snippet:

```python
class CoolStr(str):
    def __add__(self, x: int):
        return self + str(x)

a = CoolStr('test')
print(a + 1)  # output: 'test1'
```

In this example, we define a custom string class CoolStr that inherits from the built-in str class. We override the __add__ method to return a new string that is the concatenation of the current string and the converted integer.
Note that we use the str(x) function to convert the integer x to a string, so that we can concatenate it with the original string.
This code will output 'test1', which demonstrates that we have successfully "hacked" the string class to allow integer addition.

However, it's important to note that this is not a recommended way to modify the behavior of a built-in class like str. It's better to use the built-in `str.format()` method or the + operator with strings and integers, as it's more readable and maintainable.

## Boolean

What about the example in the title? Well, as you may know or infer, when a boolean value is cast to an integer, True is converted to 1 and False is converted to 0. When we perform arithmetic operations on a boolean value and an integer, type coercion converts the boolean value to an integer, making the magic happen.

## Conclusion

I hope this information was useful for you. In short, Python is a powerful language with workarounds about type coercion.
Finally, there are libraries, like Numpy, which can help handle strong typing in case your work involves strict data type.