質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

279閲覧

numpyを使わないブロードキャスト

shmpwk

総合スコア13

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/12/11 06:12

pythonでnumpy を使わずにブロードキャストして演算をしたいです。
具体的には、オブジェクトや数値をユーザー定義の演算子を使って計算します。
例えば、下のように2要素持つVector同士の足し算と、Vectorと数値の足し算はどのように実現できるでしょうか。
以下の例ではself.position += self.valでエラーが出ます。

python

1class Vector: 2 def __init__(self, x, y): 3 self.x = x 4 self.y = y 5 def __add__(self, v): 6 self.x = self.x + v.x 7 self.y = self.y + v.y 8 return self 9 10 11class Run(): 12 def __init__(self, x, y): 13 self.position = Vector(x, y) 14 self.val = 100 15 16 17 def run(self): 18 self.position+= self.position #Vector + Vector なので、__add__で計算可能 19 self.position += self.val #Vector + 数値 なので、__add__で計算不可能 20 21 22eco = Run(*np.random.rand(2)) 23 24eco.run() 25 26

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiracamus

2019/12/11 06:33

self.position += self.val でどんな値になることを期待していますか?
shmpwk

2019/12/11 07:10 編集

`self.position += self.val`は`self.position.x += self.val`と`self.position.y += self.val`を期待しています。
guest

回答2

0

ベストアンサー

まず質問文の実装はVector同士でも問題があります。本筋とはさほど関係ありませんが、後の説明がややこしくなるので言っておきます。

端的に言うと、__add__では状態が変化しないことが期待されるので、新たなオブジェクトを生成して返すようにしておいた方が良いです。

python

1 def __add__(self, v): 2 return Vector(self.x + v.x, self.y + v.y) 3

さて、本題です。

まず、引数の型を見て分岐させるようにします。

python

1 def __add__(self, v): 2 if isinstance(v, Vector): 3 return Vector(self.x + v.x, self.y + v.y) 4 else: 5 # 何かする

ナイーブなやり方としては、こういう感じとか。

python

1class Vector: 2 def __init__(self, x, y): 3 self.x = x 4 self.y = y 5 def __add__(self, v): 6 if isinstance(v, Vector): 7 return Vector(self.x + v.x, self.y + v.y) 8 elif isinstance(v, (int, float, complex)): 9 return Vector(self.x + v, self.y + v) 10 else: 11 return NotImplemented 12 13 def __repr__(self): 14 return "Vector(x={}, y={})".format(self.x, self.y)

こうすると、

python

1v = Vector(1, 2) 2print(v) # ok 3print(v + v) # ok 4print(v + 1) # ok 5print(1 + v) # TypeError: unsupported operand type(s) for +: 'int' and 'Vector'

となるので、__radd__を形式的に作ると良いでしょう。

python

1class Vector: 2 def __init__(self, x, y): 3 self.x = x 4 self.y = y 5 6 def __add__(self, v): 7 if isinstance(v, Vector): 8 return Vector(self.x + v.x, self.y + v.y) 9 elif isinstance(v, (int, float, complex)): 10 return Vector(self.x + v, self.y + v) 11 else: 12 return NotImplemented 13 14 def __radd__(self, v): 15 return self.__add__(v) 16 17 def __repr__(self): 18 return "Vector(x={}, y={})".format(self.x, self.y) 19

これくらいあればごく基本的な加算だけはだいたい不満感なく行えるかと思います。ちょっと複雑なケースを想定するとまだまともに動かない部分もあると思います(把握していませんが)。

本気で実装するのであれば、言語リファレンスのデータモデルをよく読みながら取り組むことをおすすめします。

3. データモデル — Python 3.8.1rc1 ドキュメント

投稿2019/12/11 06:39

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shmpwk

2019/12/11 07:46

非常に丁寧にご回答ありがとうございます。一気に理解が深まりました。
guest

0

おそらくisinstanceを使う方法が一番簡単です。

Python

1# 破壊的なメソッドなので、addよりiaddが適切かと 2def __iadd__(self, v): 3 if not isinstance(v, Vector): 4 v = Vector(v, v) 5 6 self.x = self.x + v.x 7 self.y = self.y + v.y 8 return self

投稿2019/12/11 06:21

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shmpwk

2019/12/11 07:18

add, isinstance便利ですね。いつも迅速なご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問