回答編集履歴

3

修正

2018/07/28 08:28

投稿

tachikoma
tachikoma

スコア3601

test CHANGED
@@ -112,7 +112,9 @@
112
112
 
113
113
  A = MyClass(-2)
114
114
 
115
- print(abs(A))
115
+ print(myabs(A)) # 自作のabs
116
+
117
+ print(abs(A)) # Python のbuilt-inのabs
116
118
 
117
119
  ```
118
120
 

2

補足

2018/07/28 08:28

投稿

tachikoma
tachikoma

スコア3601

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ```Python
4
4
 
5
- abs_made = lambda X : X if X > 0 else -X
5
+ abs_made = lambda x : x if x > 0 else -x
6
6
 
7
7
  ```
8
8
 
@@ -31,3 +31,91 @@
31
31
  print(abs_made(mat)) # fail
32
32
 
33
33
  ```
34
+
35
+
36
+
37
+ ----
38
+
39
+
40
+
41
+ ----
42
+
43
+
44
+
45
+ ----
46
+
47
+
48
+
49
+ ----
50
+
51
+
52
+
53
+ `__abs__`の話はクラスを知らないと難しいので、興味がない限りスルーしてください。と断った上で続けます。
54
+
55
+
56
+
57
+ `__abs__`は主にbuilt-in関数の`abs`によって呼び出される(オブジェクト固有の)メソッドです。`numpy.ndarray`という行列の型の場合だと、`np.absolute`と同じです。
58
+
59
+ [https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.absolute.html]
60
+
61
+ (https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.absolute.html)
62
+
63
+
64
+
65
+ 疑似コードだとこういう順序です。
66
+
67
+ ```Python
68
+
69
+ def myabs(x):
70
+
71
+ try:
72
+
73
+ #
74
+
75
+ print("試しにx.__abs__()を呼んでみます")
76
+
77
+ return x.__abs__()
78
+
79
+ except AttributeError:
80
+
81
+ # Xが__abs__を実装していない場合
82
+
83
+ print("x.__abs__()なんてありませんでしたorz")
84
+
85
+ return x if x > 0 else -x
86
+
87
+ ```
88
+
89
+
90
+
91
+ 自前で`x`が`__abs__`を実装したクラスの例は次の通りです。
92
+
93
+ ```Python
94
+
95
+ class MyClass:
96
+
97
+ def __init__(self, x):
98
+
99
+ self.x = x
100
+
101
+ def __abs__(self):
102
+
103
+ # absに呼び出してもらうための関数
104
+
105
+ # 試しに違う絶対値を実装してみる
106
+
107
+ print(" MyClassの__abs__だよ")
108
+
109
+ return (self.x ** 2) ** (1/2)
110
+
111
+
112
+
113
+ A = MyClass(-2)
114
+
115
+ print(abs(A))
116
+
117
+ ```
118
+
119
+
120
+
121
+ こんな仕組みが用意されている理由の一つとして考えられ得るのは、数学の絶対値`abs`にいろんな定義があるためです。一例を上げると、質問の中にある絶対値の定義は複素数の絶対値の定義と異なります。そうすると、実数なら・・・複素数なら・・・と様々な定義を`abs`関数に埋め込まないと行けなくなってしまい、とても複雑な関数になってしまいかねません。それを避けるための仕組みなのですが、逆に自分でクラスを作らない限りはこの仕組を意識することはないと思います。

1

補足

2018/07/28 08:26

投稿

tachikoma
tachikoma

スコア3601

test CHANGED
@@ -5,3 +5,29 @@
5
5
  abs_made = lambda X : X if X > 0 else -X
6
6
 
7
7
  ```
8
+
9
+
10
+
11
+
12
+
13
+ ----
14
+
15
+ 補足
16
+
17
+
18
+
19
+ Pythonのabsは絶対値を計算するまえに対象のオブジェクトが持っている`__abs__`メソッドがあるかを確認しに行きます。numpyの行列を考えるとこのままじゃまずいですし。
20
+
21
+ ```
22
+
23
+ import numpy as np
24
+
25
+ mat = np.array([-1, 1])
26
+
27
+ print(abs(mat)) # ok
28
+
29
+ print(mat.__abs__()) # abs(mat)は実際にはこう動く
30
+
31
+ print(abs_made(mat)) # fail
32
+
33
+ ```