

下記のコードで、self.nがインスタンス変数として定義されてるのは理解できるのですが、なぜother.nが定義されてないのにこのコードはしっかりと動くのか教えてください。  
初心者ですがよろしくおねがいします。

[code]

    class AlwaysPositive:
        def __init__(self, number):
            self.n = number
    
        def __add__(self, other):
            return abs(self.n +
                   other.n)
    
    x = AlwaysPositive(-20)
    y = AlwaysPositive(10)
    
    print(x + y)
    
[/code]


CC BY-SA 4.0
2018-12-02T07:12:27.383
50826
2018-12-03T03:53:26.593
2018-12-02T08:07:20.347
30006
30006
question
python python3
何故このコードはしっかり動くんですか？


## 動作の確認

[code]

    x = AlwaysPositive(-20)
    
[/code]

この記述によってAlwaysPositiveクラスの__init__メソッドが呼ばれてx.nに-20がセットされるのはわかりますか？  
同様に

[code]

    y = AlwaysPositive(10)
    
[/code]

この記述によってy.nに10がセットされます。

[code]

    x+y
    
[/code]

この記述によって、xはAlwaysPositive型であるので、AlwaysPositive型の__add__メソッドが呼び出されます。

## otherに対する制約

問題なのはxとyの型にはどのような制約がかかっているかです。y(other)もAlwaysPositive型でなければならないと考えるかもしれませんが実際はy.nを持てば動きます。

[code]

    class HasN():
        def __init__(self,n):
            self.n = n 
    y =HasN(15)
    print(x+y) #=> 5が返る
    
[/code]

一方でy=15などとして、y.nを持たないような値に対してx+yを実行しようとしても実行時エラーを返します。

## 動的型付け言語におけるダックタイピング

pythonなどの動的型付け言語においては、otherに対して強い型制約を要求しません。otherがnという属性を持つのであればそれにアクセスし、それで計算不能になるならば実行時エラーを出すという柔軟な取り扱いをします。このようなotherがother.nを持つならばどのような型でもよいという性質のことをダックタイピングと呼ぶことがあります。


CC BY-SA 4.0
2018-12-02T07:52:12.980
50828
2018-12-02T07:54:57.177
2018-12-02T07:54:57.177
25980
25980
50826
answer


[naoki fujita](https://ja.stackoverflow.com/users/25980/naoki-
fujita)さんの[回答](https://ja.stackoverflow.com/a/50828/25936)の前半をもう少し噛み砕いてみました。

[code]

    class AlwaysPositive:
        def __init__(self, number):
            self.n = number
    
        def __add__(self, other):
            return abs(self.n +
                   other.n)
    
[/code]

AlwaysPositiveというクラスを作って

[code]

    x = AlwaysPositive(-20)
    
[/code]

AlwaysPositiveクラスの`__init__`が呼び出されて`x.n=-20`である`x`が定義されました。

[code]

    y = AlwaysPositive(10)
    
[/code]

同様に`y.n=10`である`y`が定義されて、

[code]

    print(x + y)
    
[/code]

`x + y`の結果が表示されます。  
このとき`x + y`を計算するためにAlwaysPositiveクラスの`__add__`が呼び出されます。  
言い換えると`__add__(x, y)`が実行されるので、

[code]

    return abs(x.n +
               y.n)
    
[/code]

が返ってきます。  
というわけでこの場合`other.n`はしっかりと定義されています。


CC BY-SA 4.0
2018-12-03T03:53:26.593
50849
2018-12-03T03:53:26.593
25936
50826
answer