How to introspectively modify nodes from Python Ok, this is quite a weird case.
TL;DR

Why (and how is it Pythonically possible that) Blender's nodes dont have the __dict__ attribute.

How to programatically add attributes to them without this attribute. (No, I am not going to use exec(), thank you very much. The incoming data is royally untrusted.)


First problem
I am trying to deserialize a bunch of nodes that I previously saved to JSON. I have one somewhat working solution to this, but it involves exec(). The basic idea is that I have an assignment written like this into JSON:
&quot;a&quot;:b
Which should as the file is read become:
&lt;reference to newly created node&gt;.a = b
However I don't want to run the actual thing for security reasons, so what I actually want to do is this:

Add the field a to the node
Assign the field to whatever b is. (B is always a litteral value)

So, naively I tried this:
&lt;reference to the node&gt;.__dict__[a] = b
Python didn't like it:
'ShaderNodeMixRGB' object has no attribute '__dict__'
Yet when running dir() on the node, '__dict__' shows up. As the very first result, to be exact.
I find all this very puzzling: I didn't even know an object in Python can exist without a __dict__ attribute. Now I know the nodes are some kind of twisted wrapper around C and in some cases the very C is a wrapper around OSL. But still?
Nevertheless, I continued my search. Trying a static assignment on the node didn't work. (By this I mean &lt;reference to the node&gt;.foo = &quot;bar&quot;. It seems to be blocked by __slots__. A simmilar assignment worked in the code with the exec(). And I honestly can't say why.
At this point I started thinking something was terribly wrong with my machine. I switched over to another, which had:

A different processor architechture
A different operating system
A different version of Blender (the first thing was with an unstable one)

but still it had the same problem. Thinking some external factor had changed, I tried the old code. And it worked.
So what is going on?
Second problem
One may set an attribute's attribute's value (&lt;reference to node&gt;.inputs[&quot;foobar&quot;] = &quot;baz&quot; being the most common case) in the file. This works like a charm on the exec()-based version. However, I don't see how I could make this work withous exec().
Blender data does not have a __dict__ because it doesn't persistently store a Python object for all data. That would be very memory inefficient.

Set value for built-in and user defined properties of the node type:

setattr(node, property_name, property_value)


Set node input socket value:

node.inputs[socket_name].default_value = socket_value


For properties for one specific node you can use the method mentioned in the other answer:

node[property_name] = property_value