Are numpy arrays passed by reference?

前端 未结 3 1767
轮回少年
轮回少年 2020-12-07 11:17

I came across the fact that numpy arrays are passed by reference at multiple places, but then when I execute the following code, why is there a difference betwe

3条回答
  •  北荒
    北荒 (楼主)
    2020-12-07 11:38

    Python passes the array by reference:

    $:python
    ...python startup message
    
    >>> import numpy as np
    >>> x = np.zeros((2,2))
    >>> x
    array([[0.,0.],[0.,0.]])
    >>> def setx(x):
    ...    x[0,0] = 1
    ...
    >>> setx(x)
    >>> x
    array([[1.,0.],[0.,0.]])
    

    The top answer is referring to a phenomenon that occurs even in compiled c-code, as any BLAS events will involve a "read-onto" step where either a new array is formed which the user (code writer in this case) is aware of, or a new array is formed "under the hood" in a temporary variable which the user is unaware of (you might see this as a .eval() call).

    However, I can clearly access the memory of the array as if it is in a more global scope than the function called (i.e., setx(...)); which is exactly what "passing by reference" is, in terms of writing code.


    And let's do a few more tests to check the validity of the accepted answer:

    (continuing the session above)
    >>> def minus2(x):
    ...    x[:,:] -= 2
    ...
    >>> minus2(x)
    >>> x
    array([[-1.,-2.],[-2.,-2.]])
    

    Seems to be passed by reference. Let us do a calculation which will definitely compute an intermediate array under the hood, and see if x is modified as if it is passed by reference:

    >>> def pow2(x):
    ...    x = x * x
    ...
    >>> pow2(x)
    >>> x
    array([[-1.,-2.],[-2.,-2.]])
    

    Huh, I thought x was passed by reference, but maybe it is not? -- No, here, we have shadowed the x with a brand new declaration (which is hidden via interpretation in python), and python will not propagate this "shadowing" back to global scope (which would violate the python-use case: namely, to be a beginner level coding language which can still be used effectively by an expert).

    However, I can very easily perform this operation in a "pass-by-reference" manner by forcing the memory (which is not copied when I submit x to the function) to be modified instead:

    >>> def refpow2(x):
    ...    x *= x
    ...
    >>> refpow2(x)
    >>> x
    array([[1., 4.],[4., 4.]])
    

    And so you see that python can be finessed a bit to do what you are trying to do.

提交回复
热议问题