Right, the argument x is converted to a Python representation using PyObject(x), which makes a copy (because Python does not know how to use a Julia Any array – the underlying memory representations are different). This object is passed to the closure, appended-to, and promptly forgotten.
However, there are several object types which do have transparent sharing: PyVector, and typed arrays (which will be converted to numpy arrays on the Python side, pointing to the same memory location as in Julia).
e.g. PyVector:
julia> x = PyVector([1,2,3])
...
julia> app(x)
julia> x
4-element Int64 PyVector:
1
2
3
1
Thank you for this. That works for me now. But one thing I don’t understand yet:
app = pyeval("lambda x: x.append(1)")
x = Float64[]
app(x)
throws an error
ERROR: PyError (:PyObject_Call) <type 'exceptions.AttributeError'>
AttributeError("'numpy.ndarray' object has no attribute 'append'",)
File "PyCall.jl", line 1, in <lambda>
But doesn’t PyVector(x) convert to a numpy array as well? What is the difference?