python:変数が配列かスカラーかを識別する方法


283

引数を取る関数がありますNBins。この関数をスカラー50または配列で呼び出したいのですが[0, 10, 20, 30]。関数内でどのようにして長さを特定できNBinsますか?それともスカラーまたはベクトルの場合は別の言い方をしますか?

私はこれを試しました:

>>> N=[2,3,5]
>>> P = 5
>>> len(N)
3
>>> len(P)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
>>> 

見ての通り、私は適用することはできませんlenP、それは、配列ではないのですから、......のようなものがあるisarrayisscalarのpythonでは?

ありがとう


3
それをテストしてみましたtypeか?
スクリットカラ2013年

回答:


390
>>> isinstance([0, 10, 20, 30], list)
True
>>> isinstance(50, list)
False

あらゆるタイプのシーケンスをサポートするcollections.Sequenceには、の代わりにチェックしますlist

isinstanceクラスのタプルもサポートします。チェックtype(x) in (..., ...)は回避する必要があり、不要です。

あなたもチェックしたいかもしれません not isinstance(x, (str, unicode))


3
おかげで、listスカラーに対してfalseになるように反転することを想像していませんでした...おかげで
otmezger 2013年

3
これは素晴らしい答えですcollections.Sequenceが、文字列のABCでもあるので、それを考慮する必要があります。のようなものを使用していif type(x) is not str and isinstance(x, collections.Sequence):ます。これは素晴らしいことではありませんが、信頼できます。
bbenne10 14

2
@ bbenne10確かに、しかし避けてくださいtype、そしてnot isinstance(x, (str, unicode))Python 2 もチェックしてください
jamylak '10

なぜ「(...、...)のタイプ(x)をチェックするのは避けた方がいい、不必要だ」と言ったのですか?あなたがそう言うなら、それは理由を説明するのにとても親切です、なぜそれを避けなければならないのか疑問に思うのは私だけではないでしょう。
Olivier Pons


118

以前の回答は、配列がpython標準リストであると想定しています。numpyを頻繁に使用する人として、私は非常にpythonicテストをお勧めします:

if hasattr(N, "__len__")

12
文字列には__len__属性があります(
つまり

20
if hasattr(N, '__len__') and (not isinstance(N, str))文字列を適切に考慮します。
Thucydides411 2014年

1
Python 3の口述も説明します
Bruno Henrique

44

@jamylakと@ jpaddison3の回答を組み合わせると、入力としてnumpy配列に対して堅牢で、リストと同じように処理する必要がある場合は、

import numpy as np
isinstance(P, (list, tuple, np.ndarray))

これは、リスト、タプル、およびnumpy配列のサブクラスに対して堅牢です。

そして、(リストとタプルだけでなく)シーケンスの他のすべてのサブクラスに対してもロバストになりたい場合は、

import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))

なぜ目標値isinstanceと比較するのtype(P)ではなく、このようにすべきなのですか?以下は、NewListリストの自明なサブクラスであるの動作を作成して調査する例です。

>>> class NewList(list):
...     isThisAList = '???'
... 
>>> x = NewList([0,1])
>>> y = list([0,1])
>>> print x
[0, 1]
>>> print y
[0, 1]
>>> x==y
True
>>> type(x)
<class '__main__.NewList'>
>>> type(x) is list
False
>>> type(y) is list
True
>>> type(x).__name__
'NewList'
>>> isinstance(x, list)
True

かかわらずxyしてそれらを扱う、等しいと比較type異なる動作になるでしょう。ただし、xはのサブクラスのインスタンスなのでlist、を使用isinstance(x,list)するxy、同じように目的の動作と処理が行われます。


これが私のニーズに最も合った答えです。セットも追加しました。なぜなら、私は口述に対して頑強になりたくないからです。isinstance(P, (list, tuple, set, np.ndarray))
サンティアゴ

32

numpyにisscalar()に相当するものはありますか?はい。

>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True

6
それはより良い例です:を>>> np.isscalar('abcd')返しますTrue
Syrtis Major 2016

ありがとう!これは上記のどれよりもはるかに一般的な例であり、推奨されます。また、OPの質問に対する直接の回答でもあります。
クリストバルシフォン2018年

1
いいね。ただし、isscalar(None)はFalseを返します。Numpyはこれを次のように実装しますreturn (isinstance(num, generic) or type(num) in ScalarType or isinstance(num, numbers.Number))
Shital Shah

5
いいえ、悲しいことに。このnumpy.isscalar()関数には、多くの調整不可能な設計上の欠陥があり、将来のリビジョンで廃止される可能性があります。公式ドキュメントを言い換えるnp.ndim(x) == 0np.isscaler(x)、「前者も0d配列に対して正しくtrueを返すため、ほとんどすべての場合で、の代わりに使用する必要があります。」numpy.isscalar()したがって、に対する堅牢な前方互換性のある代替手段は、簡単にラップすることnumpy.ndim()です。たとえば、def is_scalar(obj): return np.ndim(obj) == 0
Cecil Curry

np.isscalar混乱を招くので、実際にはこれを賛成すべきではありません。公式ドキュメントは、使用して提案np.array.ndimすなわち、どこでもnp.isscalar(np.array(12))あるため、スカラーとして考慮されるべきであるFalseでnp.array(12).ndim0です
knh190

17

@jamylakのアプローチはより良いものですが、ここに代替アプローチがあります

>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (tuple, list)
False
>>> type(N) in (tuple, list)
True

2
回答に反対票を投じた人にも理由があったら良かったのに。
Sukrit Kalra 2013年

私は実際に賛成していますが、2.7では機能しないことに気付きました。 <モジュール>の行1、
オレグGryb

@OlegGryb:試してくださいtype(p) in (list, )
Sukrit Kalra 14年

ああ、それはリストではなく右側のタプルです、それを理解しました、ありがとう、そしてそれは今動作します。私は2回
投票

3

別の代替アプローチ(クラスプロパティの使用):

N = [2,3,5]
P = 5

type(N).__name__ == 'list'
True

type(P).__name__ == 'int'
True

type(N).__name__ in ('list', 'tuple')
True

何もインポートする必要はありません。


3

これが私が見つけた最良のアプローチです:__len__との存在を確認してください__getitem__

あなたはなぜ尋ねるかもしれませんか?理由は次のとおりです。

  1. isinstance(obj, abc.Sequence)PyTorchのTensorを含む一部のオブジェクトでは実装されていないため、一般的なメソッドは失敗します__contains__
  2. 残念ながら、Pythonのcollections.abcには、チェックのみを行うものはなく__len____getitem__配列のようなオブジェクトに対する最小限のメソッドだと思います。
  3. リスト、タプル、ndarray、Tensorなどで動作します。

さて、さらなる苦労はありません:

def is_array_like(obj, string_is_array=False, tuple_is_array=True):
    result = hasattr(obj, "__len__") and hasattr(obj, '__getitem__') 
    if result and not string_is_array and isinstance(obj, (str, abc.ByteString)):
        result = False
    if result and not tuple_is_array and isinstance(obj, tuple):
        result = False
    return result

ほとんどの場合、文字列を配列ではなく値と見なしたい場合があるため、デフォルトのパラメータを追加したことに注意してください。タプルについても同様です。


2
>>> N=[2,3,5]
>>> P = 5
>>> type(P)==type(0)
True
>>> type([1,2])==type(N)
True
>>> type(P)==type([1,2])
False

2

変数のデータ型を確認できます。

N = [2,3,5]
P = 5
type(P)

Pのデータ型として出力されます。

<type 'int'>

そのため、それが整数または配列であることを区別できます。


2

私はそのような基本的な質問がpythonですぐに答えを持っているようには見えないことに驚いています。提案された回答のほとんどすべてが、ある種の型チェックを使用しているようです。これは通常、Pythonでは推奨されておらず、特定のケースに制限されているようです(タプルやリストではない、さまざまな数値型または汎用の反復可能なオブジェクトでは失敗します)。

私にとって、よりうまく機能するのは、numpyをインポートしてarray.sizeを使用することです。次に例を示します。

>>> a=1
>>> np.array(a)
Out[1]: array(1)

>>> np.array(a).size
Out[2]: 1

>>> np.array([1,2]).size
Out[3]: 2

>>> np.array('125')
Out[4]: 1

また注意してください:

>>> len(np.array([1,2]))

Out[5]: 2

だが:

>>> len(np.array(a))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-40-f5055b93f729> in <module>()
----> 1 len(np.array(a))

TypeError: len() of unsized object

また、それらのいずれもジェネレーターを扱っていないように思われることにも驚いています。
RhysC 2016年

2

size代わりに単に使用してlenください!

>>> from numpy import size
>>> N = [2, 3, 5]
>>> size(N)
3
>>> N = array([2, 3, 5])
>>> size(N)
3
>>> P = 5
>>> size(P)
1

2
NameError:名「サイズ」が定義されていません
サング

1
それは本当だ。気づかずに派手なサイズを使っていました。あなたは必要とする:numpyのインポートサイズから
マチューVillion

2
np.size(5)np.size([5])== 1なので、これはタイプを正しく区別しません(つまり、スカラーを識別しません)。これが目標だと思います。
マイケル

これは興味深い発言です。元の質問は、Matlab関数であるisscalarを参照しています。Matlabでは、スカラーとサイズ1の配列の間に違いはまったくありません。これは、ベクトルでもN次元配列でもかまいません。私見、これはMatlabにとってプラスです。
Mathieu Villion 2017

0

preds_test [0]の形状(128,128,1)isinstance()関数を使用してそのデータ型をチェックしましょうisinstanceは2つの引数を取ります。1番目の引数はデータ2番目の引数はデータ型isinstance(preds_test [0]、np.ndarray)は出力をTrueにします。これは、preds_test [0]が配列であることを意味します。


0

タイトルの質問に答えるには、変数がスカラーかどうかを直接確認する方法は、変数を浮動小数点数に変換することです。を取得した場合TypeError、そうではありません。

N = [1, 2, 3]
try:
    float(N)
except TypeError:
    print('it is not a scalar')
else:
    print('it is a scalar')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.