たしかに不思議ですよね。
numpy.ndarray.reshapeのドキュメンテーション
によると
Notes
Unlike the free function numpy.reshape, this method on ndarray allows the elements of the shape parameter to be passed in as separate arguments. For example, a.reshape(10, 11) is equivalent to a.reshape((10, 11)).
となっていて、
「a.reshape(10, 11) と a.reshape((10, 11))は同じ」(=シンタックスシュガー)
になるそうです。dkato0077さんの回答はこちらに基づいていると思われます。
次に、同じページにはこの関数(ndarray.reshape)自体が以下の関数と同等という記載がありますので、そちらを見てみましょう。
numpy.reshape
numpy.reshapeのドキュメンテーション
そのnewshapeにshapeに関する説明があります。
newshape : int or tuple of ints
The new shape should be compatible with the original shape. If an integer, then the result will be a 1-D array of that length. One shape dimension can be -1. In this case, the value is inferred from the length of the array and remaining dimensions.
翻訳すると
新しい形状は、元の形状と互換性がなければなりません。整数の場合、結果はその長さの1次元配列になります。1つの形状寸法は-1とすることができる。この場合、値は配列の長さと残りの次元から推測されます。
「整数の場合、結果はその長さの1次元配列になります。」ということで、この仕様に沿った動作をしていることになります。ちなみにー1でもよいということなので、以下のコードはすべて等価になります。
python
1import numpy as np
2v = np.arange(9).reshape(3,3)
3print(v)
4x = v.reshape(9)
5print(x) # [0 1 2 3 4 5 6 7 8]
6y = v.reshape(-1,)
7print(y) # [0 1 2 3 4 5 6 7 8]
8z = np.ravel(v)
9print(z) # [0 1 2 3 4 5 6 7 8]