4

多くの数値配列計算を必要とする Python のプロジェクトに取り組んでいます。残念ながら (または、幸いなことに、あなたの視点によっては)、私は Python を初めて使用しますが、MATLAB と Octave プログラミング (それ以前は APL) を何年も行ってきました。私は、すべての変数が自動的に行列 float に型付けされることに非常に慣れており、入力型をチェックすることにまだ慣れています。

私の関数の多くでは、入力 Snumpy.ndarrayが size(n,p)である必要があるため、 type(S) がであることをテストしnumpy.ndarray、値を取得する必要があります(n,p) = numpy.shape(S)。潜在的な問題の 1 つは、入力が list/tuple/int/etc になる可能性があることです。別の問題は、入力が shape ():の配列になる可能性があることですS.ndim = 0。変数の型を同時にテストし、問題を修正してS.ndim = 0から、次のようにディメンションを取得できることに気づきました。

# first simultaneously test for ndarray and get proper dimensions
try:
    if (S.ndim == 0):
        S = S.copy(); S.shape = (1,1);
    # define dimensions p, and p2
    (p,p2) = numpy.shape(S);
except AttributeError:  # got here because input is not something array-like
    raise AttributeError("blah blah blah");

それは機能しますが、これが有効なことなのだろうか?ndim のドキュメント文字列は言う

まだ ndarray でない場合は、変換が試行されます。

そして、numpy が int/tuple/list を配列に簡単に変換できることは確かにわかっているので、numpy がこれを行う必要があるのに、なぜこれらの型の入力に対して AttributeError が発生するのか混乱しています

numpy.array(S).ndim;

これはうまくいくはずです。

4

3 に答える 3

4

NumPy コードの入力検証を行うときは、常に以下を使用しますnp.asarray

>>> np.asarray(np.array([1,2,3]))
array([1, 2, 3])
>>> np.asarray([1,2,3])
array([1, 2, 3])
>>> np.asarray((1,2,3))
array([1, 2, 3])
>>> np.asarray(1)
array(1)
>>> np.asarray(1).shape
()

この関数には、必要な場合にのみデータをコピーするという優れた機能があります。入力がすでに であるndarray場合、データはその場に残されます (厄介な も削除されるため、型のみが変更される可能性がありますnp.matrix)。

ndim のドキュメント文字列は言う

これは function の docstring であり、 NumPy 以外のオブジェクトにはnp.ndimないndim属性ではありません。その関数を使用することもできますが、データが 2 回コピーされる可能性があるため、代わりに次のようにします。

S = np.asarray(S)
(p, p2) = S.shape

これにより、ValueErrorifが発生しS.ndim != 2ます。

;[最終的な注意:インデントの規則に従うだけであれば、Python では必要ありません。実際、Python プログラマーはセミコロンを避けています。]

于 2012-09-20T14:34:25.033 に答える
3

@larsmansの回答へのコメントを考えると、次のことを試すことができます:

if not isinstance(S, np.ndarray):
    raise TypeError("Input not a ndarray")
if S.ndim == 0:
    S = np.reshape(S, (1,1))
(p, p2) = S.shape

まず、 がS(のサブクラス)かどうかを明示的に確認しますndarray。次に、必要に応じて を使用しnp.reshapeてデータをコピーします (もちろん、データを再形成します)。やっと次元が見えてきました。

ほとんどの場合、np関数は最初に a の対応するメソッドにアクセスしようとしndarray、次に入力を に変換しようとすることに注意してくださいndarray( のようにサブクラスのままにする場合もnp.asanyarrayあれば、 ( のように) そうでない場合もありnp.asarray(...)ます)。つまり、常に関数よりもメソッドを使用する方が効率的です。それが、 S.shapeand notを使用している理由ですnp.shape(S)

別のポイント: 、np.asarraynp.asanyarray...np.atleast_1Dはすべて、より一般的な関数 の特定のケースですnp.array。たとえばasarray、オプションのcopy引数arraytoFalseasanyarray設定し、同じことを行い、sets subok=Trueatleast_1Dsets ndmin=1atleast_2dsets ... 言い換えると、適切な引数ndmin=2を使用する方が常に簡単です。np.arrayしかし、いくつかのコメントで述べたように、それはスタイルの問題です。多くの場合、ショートカットを使用すると読みやすさが向上します。これは、常に念頭に置いておくべき目的です。

いずれにせよ、 を使用するときnp.array(..., copy=True)は、初期データのコピーを明示的に要求していることになりますlist([....])。他に何も変更がない場合でも、データはコピーされます。これには欠点と利点があります (フランス語で言うように)。たとえば、orderを row-firstCから column- first に変更できますF。とにかく、あなたはあなたが欲しかったコピーを手に入れます。

ではnp.array(input, copy=False)、常に新しい配列が作成されます。inputこの後者がすでにある場合と同じメモリブロックを指すかndarray(つまり、メモリの無駄がない)、そうinputでない場合は「最初から」新しいブロックを作成します。興味深いケースは、inputもちろんndarray.

この新しい配列を関数で使用すると、元の入力が変更される場合と変更されない場合がありますが、関数によって異なります。コピーを返すかどうかを確認するには、使用する関数のドキュメントを確認する必要があります。NumPy の開発者は (Python の例に従って) 不必要なコピーを制限しようと懸命に努力していますが、避けられない場合もあります。ドキュメンテーションは、何が起こるかを明示的に伝える必要があります。そうでない場合や不明な場合は、それについて言及してください。

np.array(...)何かがうまくいかない場合、いくつかの例外が発生する可能性があります。たとえば、dtype=floatのような入力でa を使用しようとすると、 ["STRING", 1]aが発生しValueErrorます。ただし、すべてのケースでどの例外が発生したか思い出せないことを認めなければなりません。適宜、この投稿を編集してください

于 2012-09-20T15:13:23.677 に答える
2

スタックオーバーフローへようこそ。これはほとんどスタイルの選択に帰着しますが、この種の状況に対処するために私が見た中で最も一般的な方法は、入力を配列に変換することです。Numpyは、このための便利なツールをいくつか提供しています。numpy.asarrayすでに言及されていますが、ここにいくつかあります。numpy.at_least1dに似てasarrayいますが、()配列を(1、)にnumpy.at_least2d再形成しますが、上記と同じですが、0dおよび1d配列を2dに再形成します。つまり、(3、)から(1、3)になります。「array_like」入力を配列に変換する理由の一部は、怠惰であるという理由だけです。たとえば、より簡単に記述できる場合もありますfoo([1, 2, 3])foo(numpy.array([1, 2, 3]))、これはnumpy自体の設計上の選択でもあります。次のように機能することに注意してください。

>>> numpy.mean([1., 2., 3.])
>>> 2.0

のドキュメントでnumpy.meanは、xが「array_like」である必要があることがわかります。

Parameters
----------
a : array_like
    Array containing numbers whose mean is desired. If `a` is not an
    array, a conversion is attempted.

そうは言っても、すべての「array_like」タイプではなく、配列のみを引数として受け入れたい場合があります。

于 2012-09-20T15:24:41.823 に答える