Journey to Master Python (WIP)

ageekymonk
1,002 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

Introspection

Ability to look at the type of the object at runtime is one of powerful features of python. You can look at the type, function signature, code and even disassembled bytecode at runtime.

Handling type at runtime

We can at runtime find the type of the object and handle actions accordingly.

1
2
3
4
5
6
7
import types
def square(x):
if (type(x) != int) and (type(x) != float):
print('Type mismatch. the argument has to be int or float')
else:
return x*x
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

What if you want to find the type of the inherited object. using type(something) will not accomplish to check for parent class but isinstance(something, parentclass) will achieve it

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A:
pass
class B(A):
pass
instance_b = B()
print(f'Is instance_b is type of B = {type(instance_b) == B}') # True
print(f'Is instance_b is type of A = {type(instance_b) == A}') # False
print(f'Is instance_b is type of B = {isinstance(instance_b, B)}') # True
print(f'Is instance_b is type of A = {isinstance(instance_b, A)}') # True
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Using isinstance function we can create other checks for function, module, class etc can be implemented. Though they are already implemented in inspect module

1
2
def isFunction(x):
return isinstance(x, types.FunctionType)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The above code is exactly how isfunction function in inspect module is implemented.

Inspecting the Function Signature

You can inspect the function signature using the inspect module. you can use __annotations__ attribute to get the annotations of a function.

1
2
3
4
5
6
7
8
9
10
11
12
import types
import inspect
def square(x: int) -> int:
assert(type(x) == int)
return x*x
sig = inspect.signature(square)
print(sig.parameters)
print(square.__annotations__)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Example: Using Introspection for Validating Parameters

Below is an example where we use inspection to write a Decorator to validate if the passed parameters are of correct type.

Function Introspection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import inspect
from functools import wraps
def Validate(f):
sig = inspect.signature(f)
@wraps(f)
def _wrapper(*args, **kwargs):
bound_args = sig.bind(*args, **kwargs)
for name, val in bound_args.arguments.items():
if name in f.__annotations__:
if not isinstance(val, f.__annotations__[name]):
assert False, f'{val} should be of type {f.__annotations__[name]}'
return f(*args, **kwargs)
return _wrapper
@Validate
def square(x: int) -> int:
return x*x
@Validate
def uppercase(x: str) -> str:
return x.upper()
print(square(10))
print(uppercase("hello"))
print(uppercase(10))
print(square(1.11))
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content