組み込みのabs関数、mathモジュールのfabs関数など、Pythonには絶対値を求める方法が幾つかある。それらの使用法やユーザー定義クラスのインスタンスの絶対値を求められるように__abs__特殊メソッドを定義する例を紹介する。
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関数は引数に整数値、浮動小数点数値、複素数値などを受け取り、その絶対値を返す。使用例を以下に示す。
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関数は整数値や浮動小数点数値を受け取り、その絶対値を返す。このとき、返される値が全て浮動小数点数値となる点が組み込みの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例外が発生する。
組み込みの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関数を使うのがよいだろう。
自作のクラスでも何らかの形で絶対値を計算できるとうれしいことがある。例えば、座標を表す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
Copyright© Digital Advantage Corp. All Rights Reserved.