If I understand your question correctly, the answer is that there are a fixed number of native types supported by Python and NumPy, all of which correspond naturally to Julia types and are converted bidirectionally by PyCall. Julia and NumPy arrays are memory-compatible and Julia knows how to handle arrays with memory allocated by other systems, so conversion back and forth between Julia arrays and NumPy arrays is zero-copy. Other types like Python dicts are proxied in Julia as special types that Julia knows how to work with as dictionaries (user-defined data types are common in Julia), while general Python objects are just proxied transparently and `obj.method` calls are passed through to the embedded Python runtime. You can even define a function object `f` in Python and call it using `f()` syntax in Julia and vice versa. It's all highly transparent and smooth.