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

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

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

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

Q&A

解決済

3回答

3963閲覧

pythonでドットを用いたメソッドの使い方を教えてください。

tomomonX

総合スコア28

Python

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

0グッド

0クリップ

投稿2021/06/05 09:34

ドットを使ったメソッドの使い方が知りたい

ゼロから作るDeep Learning3という本を読んでpythonの勉強をしている初心者です。
メソッド(self,func)とfunc.メソッド(self)は同義ですか。
メソッドの使い方を教えてほしいです。下記が勉強しているコードです。

コード

class Variable: def __init__(self, data): self.data = data self.grad = None self.creator = None def set_creator(self, func):  self.creator = func def backward(self): f = self.creator # 1. Get a function if f is not None: x = f.input # 2. Get the function's input x.grad = f.backward(self.grad) # 3. Call the function's backward x.backward() class Function: def __call__(self, input): x = input.data y = self.forward(x) output = Variable(y) output.set_creator(self) # Set parent(function) self.input = input self.output = output # Set output return output def forward(self, x): raise NotImplementedError() def backward(self, gy): raise NotImplementedError() class Square(Function): def forward(self, x): y = x ** 2 return y def backward(self, gy): x = self.input.data gx = 2 * x * gy return gx class Exp(Function): def forward(self, x): y = np.exp(x) return y def backward(self, gy): x = self.input.data gx = np.exp(x) * gy return gx A = Square() B = Exp() C = Square() x = Variable(np.array(0.5)) a = A(x) b = B(a) y = C(b) # backward y.grad = np.array(1.0) y.backward() print(x.grad)

質問の本題

Functionクラスの

output.set_creator(self)

について質問したいです。
メソッドの定義では

set_creator(self, func)

としていましたが、実行するときには

output.set_creator(self)

です。これはfunctionにoutputを代入した

set_creator(self,output)

という意味になるのでしょうか。
ドットの意味を理解しきれていなく教えてほしいです。

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

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

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

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

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

guest

回答3

0

output.set_creator(self) は Variable.set_creator(output, self) と同じです。

変数名が被っているので分かりづらいですが、
呼び出し側から見た時のselfと、関数側から見た時のselfは別物です。

Python

1class MyClass: 2 def method(self, val): 3 print(f'{self=}') 4 print(f'{val=}') 5 6 7my_instance = MyClass() 8self = 42 # ふつうはselfという名前の変数を用意しませんが、あくまで例として。 9 10print(f'{my_instance=}') 11print(f'{self=}') 12print('-' * 42) 13 14my_instance.method(self) 15print('-' * 42) 16 17MyClass.method(my_instance, self) 18print('-' * 42)

実行結果 Wandbox

my_instance=<__main__.MyClass object at 0x7f7f54d5fb50> self=42 ------------------------------------------ self=<__main__.MyClass object at 0x7f7f54d5fb50> val=42 ------------------------------------------ self=<__main__.MyClass object at 0x7f7f54d5fb50> val=42 ------------------------------------------

投稿2021/06/05 10:04

編集2021/06/05 10:06
LouiS0616

総合スコア35668

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

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

tomomonX

2021/06/05 13:22

ありがとうございます。参考になりました^^
guest

0

ベストアンサー

疑問を持たれた点は、ドットの使い方の問題ではありません。
クラスで定義された通常のメソッドは第1引数を必要とします。それはselfと書くことが慣例になっていますが、文法的にはなんでも良いのです。
クラスのコンストラクタを使って作成したそのクラスのインスタンスオブジェクトはクラス内で定義されたメソッドのラッパーをメソッドとして持ちます。
そのラッパーメソッドを実行すると、ラッパーメソッドはインスタンスオブジェクトを第1引数とし、残りの引数をその後ろの引数にして、クラスで定義された元のメソッドを呼び出します。

以上の処理の結果、

output.set_creator(self)

を実行すると、output.set_creatorというラッパーが呼び出されます。
ご質問のケースが、python勉強本でわからなかったことの場合ですと、
selfはFunctionクラスかその派生クラスのインスタンスオブジェクトとなります。
それをfunctionと書くことにしましょう。
するとラッパーの呼び出しは、

output.set_creator(function)

となります。
ラッパーが呼び出すのは、Variableクラスのメソッドである、Variable.set_creatorで
その引数は、outputとfunctionとなります。
つまり

Variable.set_creator(output, function)

が呼び出されることになります。

その結果として、Variableクラスののインスタンスオブジェクトであるoutputのインスタンス変数output.creatorにFunctionクラスかその派生クラスのインスタンスオブジェクトであるfunctionが設定されることになります。

投稿2021/06/05 10:02

ppaul

総合スコア24670

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

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

tomomonX

2021/06/05 13:23

ありがとうございます。ラッパーという言葉初めて聞きました。まだまだ勉強不足です。
guest

0

質問自体が意味不明です。
(関係のない事を取り上げているため)

Python

1output.set_creator(self)

の呼び出し側はどこですか?

そう、 Function クラスの call(self, input) メソッドですね。

なので Functionクラスを渡しています。

Self は『オブジェクト自身』を指します。

ただし、Functionにとっての output はオブジェクト名が分かっています。

なので outputを渡すなら、

Python

1output.set_creator(output)

のようになるはずです。

……ここまで書いてもわかりにくいと思います。

なぜなら『オブジェクト指向がなんたるか』を理解していないためです。

そもそもオブジェクト指向( 以降 OOP ) の基本概念は、

『データ(= フィールド, プロパティ) と処理(= メソッド) をひとまとめにしたオブジェクト』なるものを中心に見る発想法です。

質問でいえば、outputとかそういうのです。

C言語等のような非OOPの言語では、データと処理は別物でした。

そこで、データと処理をひとまとめにして、オブジェクトに管理・処理を任せるという発想になりました。

これがOOP。

つまり、『対象データと処理方法はオブジェクトだけが知っている』という発想です。

それによってメッセージング(C++でいえば単なるメンバ関数呼び出し)で、『これこれをしてくれ』と命令するだけで、オブジェクト自身が勝手にやってくれるという寸法です。

そして、ドット( . ) は、『オブジェクトが持つメンバ』を示しているだけです。

メンバとは、フィールド(言語によってはプロパティ)やメソッドの事です。

クラスはこのオブジェクトの定義です。

コンパイラやインタプリタ( Pythonならインタプリタか ) に『こういうデータを持っていて、こういう処理をするやつがあるんで、よろぴく♪』と説明しているだけです。

なので

クラスを組んだったwww -> オブジェクト指向だ!!!

ではないです。

それで、Self はオブジェクト内部とかでは、名前がないので、代わりに Self というやつで示すのです。
(厳密には違うと思いますが、イメージとして)


[追記1]

よい子のC++(オブジェクト指向完全理解)をご参考ください。

私は上記のサイトさんで学びました。

(上記サイトさんはC++で説明していますが、Pythonでも発想自体は同じです。書き方とかが違うだけです)

投稿2021/06/05 09:51

編集2021/06/05 10:53
BeatStar

総合スコア4962

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

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

tomomonX

2021/06/05 10:45

コメントありがとうございます。 意識してなかったのですが、これがオブジェクト指向なんですね。 無意識のうちに、勉強している内容が、オブジェクト指向だったようですので、 オブジェクト指向の勉強始めてみます。 何を勉強したらいいかのヒントをいただき助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問