LoginSignup
3
3

More than 3 years have passed since last update.

[python] スカラーの判定方法

Last updated at Posted at 2019-11-06

入力引数がスカラーかどうかを簡単に判定したいとき,matlabだとisscalarという関数があるが,pythonの場合,どうするのがよさそうかわからなかったので調べた。

バージョン情報

こういった話はバージョン依存性があるので,本記事作成時のバージョンを残しておく。

  • python 3.7.3
  • numpy 1.17.0

方法1: Numberクラスを継承しているかどうかで判定

を読むと,こんなことが書かれている。

class numbers.Number
 数の階層の根。引数 x が、種類は何であれ、数であるということだけチェックしたい場合、isinstance(x, Number) が使えます。

コードにすると,こんな感じ。シンプルでよい。

import numbers

def is_scalar(x):
    return isinstance(x, numbers.Number)

方法2 : numpyの判定関数を使う

調べてみると,numpyにnumpy.isscalarという関数があった。仕様はこのあたりが見やすい。

ソースコード上の定義箇所はここだった。コードを見る限り,方法1よりもスカラーと判定する範囲が確実に広い。関数コメントを見る限り,strとかもスカラーとする仕様になっている(個人的にはちょっと違和感がある。strが係数になるベクトル空間とか作れるのか?)

スカラー判定の範囲

よく使いそうなオブジェクトで試したので,一応載せておく。試した中では,strbytesが方法1だとFalse,方法2(numpy.isscalar)だとTrueになり,それ以外は判定結果が一致した。実装時はこのあたりの違いに気を付けたほうがよさそう。

scalar_test.py
import numpy
import numbers
import decimal

def is_scalar(x):
    return isinstance(x, numbers.Number)

def check(input_var):
    print("=========================")
    print(input_var)
    print(type(input_var))
    print("is_sclar_1: " + str(is_scalar(input_var)))
    print("is_sclar_2: " + str(numpy.isscalar(input_var)))

if __name__ == "__main__":
    # 方法1,2ともにスカラーと判定
    var_int = 1
    var_bool = True
    var_float = 1.0
    var_complex = 1 + 1j
    var_npint32 = numpy.int32(1)
    var_decimal = decimal.Decimal('12.345')

    # 方法1はスカラー,方法2は非スカラーと判定
    var_bytes_1 = bytes(1)
    var_bytes_hoge = b'hoge'
    var_str1 = "1"
    var_str4 = "hoge"

    # 方法1,2ともに非スカラーと判定
    var_nan = None
    var_nparray = numpy.array(1)
    var_list = [1]
    var_taple = (1,2)  #(1)ならtapleにならないのでスカラーと判定される
    var_dict = {"a": 1}
    var_set = {1}

    # 検証
    check(var_int)
    check(var_bool)
    check(var_float)
    check(var_complex)
    check(var_npint32)
    check(var_decimal)

    check(var_bytes_1)
    check(var_bytes_hoge)
    check(var_str1)
    check(var_str4)

    check(var_nan)
    check(var_nparray)
    check(var_list)
    check(var_taple)
    check(var_dict)
    check(var_set)

出力結果

=========================
1
<class 'int'>
is_sclar_1: True
is_sclar_2: True
=========================
True
<class 'bool'>
is_sclar_1: True
is_sclar_2: True
=========================
1.0
<class 'float'>
is_sclar_1: True
is_sclar_2: True
=========================
(1+1j)
<class 'complex'>
is_sclar_1: True
is_sclar_2: True
=========================
1
<class 'numpy.int32'>
is_sclar_1: True
is_sclar_2: True
=========================
12.345
<class 'decimal.Decimal'>
is_sclar_1: True
is_sclar_2: True
=========================
b'\x00'
<class 'bytes'>
is_sclar_1: False
is_sclar_2: True
=========================
b'hoge'
<class 'bytes'>
is_sclar_1: False
is_sclar_2: True
=========================
1
<class 'str'>
is_sclar_1: False
is_sclar_2: True
=========================
hoge
<class 'str'>
is_sclar_1: False
is_sclar_2: True
=========================
None
<class 'NoneType'>
is_sclar_1: False
is_sclar_2: False
=========================
1
<class 'numpy.ndarray'>
is_sclar_1: False
is_sclar_2: False
=========================
[1]
<class 'list'>
is_sclar_1: False
is_sclar_2: False
=========================
(1, 2)
<class 'tuple'>
is_sclar_1: False
is_sclar_2: False
=========================
{'a': 1}
<class 'dict'>
is_sclar_1: False
is_sclar_2: False
=========================
{1}
<class 'set'>
is_sclar_1: False
is_sclar_2: False

参考URL

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3