[解決!Python]絶対値を計算するには解決!Python

組み込みのabs関数、mathモジュールのfabs関数など、Pythonには絶対値を求める方法が幾つかある。それらの使用法やユーザー定義クラスのインスタンスの絶対値を求められるように__abs__特殊メソッドを定義する例を紹介する。

» 2024年02月13日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

i = -1
f = -1.23
c = 1.0 + 1.0j

# 組み込みのabs関数
result = abs(i)
print(result)  # 1

result = abs(f)
print(result)  # 1.23

result = abs(c)
print(result)  # 1.4142135623730951

# math.fabs関数
from math import fabs

result = fabs(i)
print(result)  # 1.0

result = fabs(f)
print(result)  # 1.23

result = fabs(c)  # TypeError

# リストの要素の絶対値を求める
l = [-1., 2, -3.]
result = [abs(item) for item in l]
print(result)  # [1.0, 2, 3.0]

# numpy.abs関数
import numpy as np

result = np.abs(l)
print(result)  # [1. 2. 3.]

a = np.array(l)
print(a)  # [-1.  2. -3.]
result = np.abs(a)  #
print(result)  # [1. 2. 3.]

# __abs__特殊メソッド
class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

    def __str__(self):
        return f'({self.x}, {self.y})'    

p = Point(1, 1)
print(p)  # (1, 1)
print(repr(p))  # Point(1, 1)

result = abs(p)  # TypeError

from math import sqrt

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

    def __str__(self):
        return f'({self.x}, {self.y})'    

    def __abs__(self):
        return sqrt(self.x ** 2 + self.y ** 2)

p = Point(1, 1)
result = abs(p)  # OK
print(result)  # 1.4142135623730951


絶対値を求める幾つかの方法

 Pythonで数値の絶対値を求めるには幾つかのやり方がある。

  • 組み込みのabs関数:組み込みなのですぐに使える。整数値/浮動小数点数値/複素数値の絶対値を求められる他、__abs__特殊メソッドを実装しているクラスのインスタンスであれば、abs関数にそのインスタンスを渡すことで絶対値を求められる
  • mathモジュールのfabs関数:整数値/浮動小数点数値の絶対値を求められる。戻り値は常に浮動小数点数値
  • NumPyのnumpy.abs関数:配列やリストの要素の絶対値を一括して求められる

 以下ではこれらの関数の使い方と__abs__特殊メソッドの実装例を見ていく。

組み込みのabs関数

 組み込みのabs関数は引数に整数値、浮動小数点数値、複素数値などを受け取り、その絶対値を返す。使用例を以下に示す。

i = -1
f = -1.23
c = 1.0 + 1.0j

result = abs(i)
print(result)  # 1

result = abs(f)
print(result)  # 1.23

result = abs(c)
print(result)  # 1.4142135623730951


 注意すべき点としては、整数値を渡したときには絶対値が整数値として、浮動小数点数値を渡したときには絶対値が浮動小数点数値として返される点だ。複素数値の場合は「実数部の二乗と虚数部の二乗の和の平方根」が浮動小数点数値として返される。

mathモジュールのfabs関数

 mathモジュールのfabs関数は整数値や浮動小数点数値を受け取り、その絶対値を返す。このとき、返される値が全て浮動小数点数値となる点が組み込みのabs関数とは異なる。以下に使用例を示す。

from math import fabs

result = fabs(i)
print(result)  # 1.0

result = fabs(f)
print(result)  # 1.23

result = fabs(c)  # TypeError


 最後の行に示したように、math.fabs関数に複素数値を渡すとTypeError例外が発生する。

numpy.abs関数

 組み込みのabs関数とmath.fabs関数はどちらも単一の値を受け取り、その絶対値を返すものだ。よって、リストの要素の絶対値を求めたいようなときには、例えば、以下のようにリスト内包表記の内部でこれらを使うことになる。

l = [-1., 2, -3.]

result = [abs(item) for item in l]
print(result)  # [1.0, 2, 3.0]


 これで済むのであれば問題はないが、NumPyのnumpy.abs関数(numpy.absolute関数)にリストやNumPyの多次元配列(numpy.ndarrayオブジェクト)を与えると、それらの要素の絶対値を含む多次元配列を返す。以下に例を示す。

import numpy as np

result = np.abs(l)
print(result)  # [1. 2. 3.]


 このとき、絶対値を格納する配列(numpy.ndarrayオブジェクト)の型は統一される(上の例では整数値と浮動小数点数値を含むリストを渡しているが、絶対値は全て浮動小数点数値となっている。一方、リスト内包表記内でabs関数を使った例では整数値の絶対値は整数値となっている)。

 上の例ではリストを渡しているが、既に述べているように多次元配列を渡してもよい。以下の例ではリストから多次元配列を作成し、それをnumpy.abs関数に渡している。

a = np.array(l)
print(a)  # [-1.  2. -3.]
result = np.abs(a)  #
print(result)  # [1. 2. 3.]


 多数の要素を含むオブジェクトで絶対値を求めるのであれば、numpy.abs関数を使うのがよいだろう。

__abs__特殊メソッド

 自作のクラスでも何らかの形で絶対値を計算できるとうれしいことがある。例えば、座標を表すPointクラスを作っているとしよう。

 以下の例では、2次元座標のxとyをインスタンス変数として保持するようなPointクラスを定義している。

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

    def __str__(self):
        return f'({self.x}, {self.y})'    


 ここでは__repr__特殊メソッドと__str__特殊メソッドを定義することで、以下のような出力が得られるクラスとなっている。

p = Point(1, 1)
print(p)  # (1, 1)
print(repr(p))  # Point(1, 1)


 このとき、座標(x, y)の絶対値(原点からの距離)は「x ** 2 + y ** 2の平方根」として求められる。このことを期待して、abs関数を呼び出すと、もちろんTypeError例外が発生する。

result = abs(p)  # TypeError


 人の頭では今述べたような座標の絶対値の求め方が分かっていても、組み込みのabs関数にはそのことが分からないからだ。分かってもらうようにするには、__abs__特殊メソッドを定義(実装)する。abs関数を呼び出すと、その引数に指定したオブジェクトが__abs__特殊メソッドを持っていれば、それが呼び出され、絶対値が計算される。以下に定義例を示す。

from math import sqrt

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return f'Point({self.x}, {self.y})'

    def __str__(self):
        return f'({self.x}, {self.y})'    

    def __abs__(self):
        return sqrt(self.x ** 2 + self.y ** 2)


 このように__abs__特殊メソッドを定義することで、以下のようにPointクラスのオブジェクトの絶対値が計算できるようになった。

p = Point(1, 1)
result = abs(p)  # OK
print(result)  # 1.4142135623730951


「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。