Automatic Type Conversion in Runtime | Python

Devops at Leapfrog Technology Inc.
Search for a command to run...

Devops at Leapfrog Technology Inc.
No comments yet. Be the first to comment.
Do you understand the difference between "looks good" and "is good?"

For more than 3 years I've been doing DevOps and involved myself in multiple projects ranging from simple static web applications deployed to some CDNs to multi-tenant systems with event-driven architectures. I've always found some ways to make my bo...
One of the problems that I face frequently when writing Infrastructure as a Code is how you structure it. To answer this question, I think there are a few indicators that decide how we want to structure. One resource will have less change compared t...

This may come as a surprise to you. How can someone use nginx configuration with Javascript? Fortunately, nginx supports a language called njs which is a strict subset of ECMA5. This can be used to further extend your routing logic, but don't be that...

This is my first blog of multiple blogs on developing a pod troubleshooter turned into a compiler as a service. What do you call it CaaS? COMPaaS is cooler though, lol. I've been learning a lot of things in this journey, so I decided to share about i...

Hi. I am back with an exciting topic in python.
How many times you have come across functions which automatically convert your values to required types in runtime?
For e.g. In Django whenever you define your types like this in route definitions the URL parameters are automatically parsed inside of your function.
urlpatterns = [
path("/<str:slug>", someRandomView, name="home"),
path("/<int:pk>", someRandomProfile, name="home_profile")
]
So whenever you define your views, your data types are automatically converted to the required data type.
def someRandomView(slug):
...
def someRandomProfile(pk):
...
This offers a huge convenience in your application by automatically converting your type as per your function or something hints the function wants to achieve.
Similar behavior is achieved in fast API.
Let’s define a simple function.
def getAge(age, name):
print( f" {age} : {type(age)} , {name} : {type(name)} " )
You can see our types are nowhere defined in this piece of code. But, we can guess the user wants to age as an int variable and name as an str variable ( most probably). But python doesn’t work that way. You can call that function with any variable you want.
It would be a lot better if your code automatically gave the developer some idea about data types.
Let’s refactor that piece of code a little bit.
def getAge(age: int, name: str):
print( f" {age} : {type(age)} , {name} : {type(name)} " )
Now, this code is a lot cleaner than your previous code. But, we still have the same problem but it aids a little bit. Your text editor may flag out wrong parameter types if you’re using some linters or running on mypy.
But, what we wanted to achieve is to make automatic type conversions in runtime. So, whenever you call the function, your arguments are automatically parsed to be converted into required data types.
Let’s try writing a decorator to print what exactly we can extract out of the function definition.
from typing import Callable
def decorator(func: Callable):
def inner_func(*args, **kwargs):
print(kwargs, func.__annotations__)
func(*args, **kwargs)
return inner_func
@decorator
def getAge(age: int, name: str):
print( f" {age} : {type(age)} , {name} : {type(name)} " )
When we call the function using getAge(age=12,name=”Mahesh”), this is the output we get.
kwargs: {'age': 12, 'name': 'mahesh'}
__annotations__ : {'age': <class 'int'>, 'name': <class 'str'>}
Now, this makes sense. Your annotations are extracted from your function in the compile time of the function and not changed by your arguments.
So, to achieve automatic type conversion on the function, we can write all the code to convert types as mentioned in the function annotations.
#/bin/env python
from typing import Callable
def decorator(function: Callable):
def inner_function(*args, **kwargs):
newKwargs = {}
for argName, typeName in function.__annotations__.items():
if typeName is int:
intVar = int(kwargs[argName])
newKwargs[argName] = intVar
elif typeName is str:
strVar = str(kwargs[argName])
newKwargs[argName] = strVar
function(*args, **newKwargs)
return inner_function
@decorator
def getAge(age: int, name: str):
print( f" {age} : {type(age)} , {name} : {type(name)} " )
And boom, this works!
Whenever you call the function, it gets automatically converted to the required type and if it fails, it will throw the value error.