回答編集履歴
3
修正
    
        answer	
    CHANGED
    
    | @@ -55,7 +55,8 @@ | |
| 55 55 | 
             
                    return (self.x ** 2) ** (1/2)
         | 
| 56 56 |  | 
| 57 57 | 
             
            A = MyClass(-2)
         | 
| 58 | 
            -
            print( | 
| 58 | 
            +
            print(myabs(A))  # 自作のabs
         | 
| 59 | 
            +
            print(abs(A))  # Python のbuilt-inのabs
         | 
| 59 60 | 
             
            ```
         | 
| 60 61 |  | 
| 61 62 | 
             
            こんな仕組みが用意されている理由の一つとして考えられ得るのは、数学の絶対値`abs`にいろんな定義があるためです。一例を上げると、質問の中にある絶対値の定義は複素数の絶対値の定義と異なります。そうすると、実数なら・・・複素数なら・・・と様々な定義を`abs`関数に埋め込まないと行けなくなってしまい、とても複雑な関数になってしまいかねません。それを避けるための仕組みなのですが、逆に自分でクラスを作らない限りはこの仕組を意識することはないと思います。
         | 
2
補足
    
        answer	
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            関数を定義するだけならラムダ式でもいいかもしれませんね。
         | 
| 2 2 | 
             
            ```Python
         | 
| 3 | 
            -
            abs_made = lambda  | 
| 3 | 
            +
            abs_made = lambda x : x if x > 0 else -x
         | 
| 4 4 | 
             
            ```
         | 
| 5 5 |  | 
| 6 6 |  | 
| @@ -14,4 +14,48 @@ | |
| 14 14 | 
             
            print(abs(mat))  # ok
         | 
| 15 15 | 
             
            print(mat.__abs__())  # abs(mat)は実際にはこう動く
         | 
| 16 16 | 
             
            print(abs_made(mat))  # fail
         | 
| 17 | 
            -
            ```
         | 
| 17 | 
            +
            ```
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            ----
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            ----
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            ----
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ----
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            `__abs__`の話はクラスを知らないと難しいので、興味がない限りスルーしてください。と断った上で続けます。
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            `__abs__`は主にbuilt-in関数の`abs`によって呼び出される(オブジェクト固有の)メソッドです。`numpy.ndarray`という行列の型の場合だと、`np.absolute`と同じです。
         | 
| 30 | 
            +
            [https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.absolute.html]
         | 
| 31 | 
            +
            (https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.absolute.html)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            疑似コードだとこういう順序です。
         | 
| 34 | 
            +
            ```Python
         | 
| 35 | 
            +
            def myabs(x):
         | 
| 36 | 
            +
                try:
         | 
| 37 | 
            +
                    # 
         | 
| 38 | 
            +
                    print("試しにx.__abs__()を呼んでみます")
         | 
| 39 | 
            +
                    return x.__abs__()  
         | 
| 40 | 
            +
                except AttributeError:
         | 
| 41 | 
            +
                    # Xが__abs__を実装していない場合
         | 
| 42 | 
            +
                    print("x.__abs__()なんてありませんでしたorz")
         | 
| 43 | 
            +
                    return x if x > 0 else -x
         | 
| 44 | 
            +
            ```
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            自前で`x`が`__abs__`を実装したクラスの例は次の通りです。
         | 
| 47 | 
            +
            ```Python
         | 
| 48 | 
            +
            class MyClass:
         | 
| 49 | 
            +
                def  __init__(self, x):
         | 
| 50 | 
            +
                    self.x = x
         | 
| 51 | 
            +
                def __abs__(self):
         | 
| 52 | 
            +
                    # absに呼び出してもらうための関数
         | 
| 53 | 
            +
                    # 試しに違う絶対値を実装してみる
         | 
| 54 | 
            +
                    print("    MyClassの__abs__だよ")
         | 
| 55 | 
            +
                    return (self.x ** 2) ** (1/2)
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            A = MyClass(-2)
         | 
| 58 | 
            +
            print(abs(A))
         | 
| 59 | 
            +
            ```
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            こんな仕組みが用意されている理由の一つとして考えられ得るのは、数学の絶対値`abs`にいろんな定義があるためです。一例を上げると、質問の中にある絶対値の定義は複素数の絶対値の定義と異なります。そうすると、実数なら・・・複素数なら・・・と様々な定義を`abs`関数に埋め込まないと行けなくなってしまい、とても複雑な関数になってしまいかねません。それを避けるための仕組みなのですが、逆に自分でクラスを作らない限りはこの仕組を意識することはないと思います。
         | 
1
補足
    
        answer	
    CHANGED
    
    | @@ -1,4 +1,17 @@ | |
| 1 1 | 
             
            関数を定義するだけならラムダ式でもいいかもしれませんね。
         | 
| 2 2 | 
             
            ```Python
         | 
| 3 3 | 
             
            abs_made = lambda X : X if X > 0 else -X
         | 
| 4 | 
            +
            ```
         | 
| 5 | 
            +
             | 
| 6 | 
            +
             | 
| 7 | 
            +
            ----
         | 
| 8 | 
            +
            補足
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Pythonのabsは絶対値を計算するまえに対象のオブジェクトが持っている`__abs__`メソッドがあるかを確認しに行きます。numpyの行列を考えるとこのままじゃまずいですし。
         | 
| 11 | 
            +
            ```
         | 
| 12 | 
            +
            import numpy as np
         | 
| 13 | 
            +
            mat = np.array([-1, 1])
         | 
| 14 | 
            +
            print(abs(mat))  # ok
         | 
| 15 | 
            +
            print(mat.__abs__())  # abs(mat)は実際にはこう動く
         | 
| 16 | 
            +
            print(abs_made(mat))  # fail
         | 
| 4 17 | 
             
            ```
         | 
