Search code examples
pythonnumpymethod-chaining

Why named expression is necessary in this Numpy function chain?


This snippet:

a = np.arange(12, 0, -1).reshape(3, 4)
(a := a.flatten()).sort()
print(a)

produces

[ 1  2  3  4  5  6  7  8  9 10 11 12]

as expected. Without named expression:

a = np.arange(12, 0, -1).reshape(3, 4)
a = a.flatten().sort()
print(a)

I'm getting None. Why is that?


Solution

  • Quoting from PEP 572 – Assignment Expressions

    Syntax and semantics

    In most contexts where arbitrary Python expressions can be used, a named expression can appear. This is of the form NAME := expr where expr is any valid Python expression other than an unparenthesized tuple, and NAME is an identifier.

    The value of such a named expression is the same as the incorporated expression, with the additional side-effect that the target is assigned that value:

    So this code,

    (a := a.flatten()).sort()
    print(a)
    

    is roughly equivalent to

    a = a.flatten()
    a.sort()
    print(a)
    

    This means that you are not assigning the result of sort anywhere. You are letting a.sort() to complete and print a later(which will result in expected output)

    Remember sort is an in-place operation and it returns None, So in your second code you are assigning return value of sort(which is None).

    a = a.flatten().sort()