Keeping networkx aside. Take this code snippet.
class CallableIterable:
def __init__(self, val):
self.val = val[:]
def __call__(self, arg1=True):
print('acting as a callable')
return f'You called this with {arg1}'
def __contains__(self, arg):
print('acting as an iterable')
return arg in self.val
class Graph:
@property
def nodes(self):
return CallableIterable([1, 2, 3, 4, 5])
You can see that there are two classes CallableIterable and Graph. Graph has a property nodes that returns an instance of CallableIterable when called.
Create an instance of Graph g.
g = Graph()
Now you can use the property g.nodes in two ways.
As an iterable
print(1 in g.nodes)
This gives
acting as an iterable
True
This is because in triggers the __contains__ method of the CallableIterable class (in this example).
As a callable
print(g.nodes('some random value'))
This gives
acting as a callable
You called this with some random value
This is because it triggers the __call__ method of the CallableIterable class.
The arguments passed in (), in this case, 'some random value' of g.nodes('some random value') or in your case, data=True of Graph().nodes(data=True) are passed to the __call__ of the return value of the property (which is g.nodes), NOT TO the property decorated function Graph.nodes.
Internally this is g.nodes.__call__('some random value').
With this understanding apply the same principle to networkx, where NodeView is the type of object returned instead of the CallableIterable as seen in this example, the working is the same.
nodes = NodeView(self) is an instance of the NodeView
class.
- This class has a
__call__ and a __contains__ method.
- Which lets you use it as a callable / function
(
Graph().nodes(data=True))) and as an iterable ('something' in Graph().nodes).
The NodeView class has other functions than just __call__ and __contains__, each of which will get called appropriately.
This is essentially what the docstrings mean with the following
Can be used as `G.nodes` for data lookup and for set-like operations.
Can also be used as `G.nodes(data='color', default=None)` to return a
NodeDataView which reports specific node data but no set operations