What/where is ‘inference’ ?#
The inference is a mechanism through which astroid tries to interpret statically your Python code.
How does it work ?#
The magic is handled by
astroid usually provides inference support for various Python primitives,
such as protocols and statements, but it can also be enriched
via inference transforms.
In both cases the
infer() must return a generator which iterates
through the various values the node could take.
In some case the value yielded will not be a node found in the AST of the node
but an instance of a special inference class such as
Namely, the special singleton
Uninferable is yielded when the inference reaches
a point where it can’t follow the code and is so unable to guess a value; and
instances of the
Instance class are yielded when the current node is
inferred to be an instance of some known class.
Crash course into astroid’s inference#
Let’s see some examples on how the inference might work in
First we’ll need to do a detour through some of the
astroid offers a relatively similar API to the builtin
that is, you can do
astroid.parse(string) to get an AST out of the given
>>> tree = astroid.parse('a + b') >>> tree >>> <Module l.0 at 0x10d8a68d0> >>> print(tree.repr_tree()) Module( name='', doc=None, file='<?>', path=['<?>'], package=False, pure_python=True, future_imports=set(), body=[Expr(value=BinOp( op='+', left=Name(name='a'), right=Name(name='b')))])
repr_tree() is super useful to inspect how a tree actually looks.
Most of the time you can access the same fields as those represented
in the output of
repr_tree() so you can do
to get the left hand side operand of the addition operation.
Another useful function that you can use is
which given a string, tries to extract one or more nodes from the given string:
>>> node = astroid.extract_node(''' ... a = 1 ... b = 2 ... c ''')
In that example, the node that is going to be returned is the last node
from the tree, so it will be the
You can also use
astroid.extract_node() to extract multiple nodes:
>>> nodes = astroid.extract_node(''' ... a = 1 #@ ... b = 2 #@ ... c ''')
You can use
#@ comment to annotate the lines for which you want the
corresponding nodes to be extracted. In that example, what we’re going to
extract is two
Expr nodes, which is in astroid’s parlance, two statements,
but you can access their underlying
Assign nodes using the
Now let’s see how can we use
astroid to infer what’s going on with your code.
The main method that you can use is
infer(). It returns a generator
with all the potential values that
astroid can extract for a piece of code:
>>> name_node = astroid.extract_node(''' ... a = 1 ... b = 2 ... c = a + b ... c ''') >>> inferred = next(name_node.infer()) >>> inferred <Const.int l.None at 0x10d913128> >>> inferred.value 3
From this example you can see that
astroid is capable of inferring what
might hold, which is a constant value with the number 3.