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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

Python

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

Q&A

5回答

1866閲覧

他のクラスに存在するメソッドを監視したい。監視対象が動いた時に処理を走らせたい。

sponge_yukari

総合スコア12

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

Python

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

0グッド

1クリップ

投稿2018/09/19 02:46

編集2018/09/19 06:43

こんにちわ。
どう考えても答えにたどり着けなかったので質問します。

やりたいこと

言語はPython3.6です。
他のクラスに存在するメソッドが動いた時に、それを察知して別のクラスで別の動作を行うようにしたい。
具体的にはevent処理ですが、応用できる可能性があるのでソースには表記していません。

ソース

Python

1class A() : 2 ・・・ 3 def methodA(self) : 4 """ここを感知したい"""

Python

1class B() : 2 a = A() 3 ・・・

Python

1class main() : 2 b = B() 3 def process(self) : 4 """感知したときにこのメソッドで別の処理を動かす""" 5 ・・・

具体例ではなく申し訳ありません。
__init__等入れてませんが、これで伝われば幸いです。

条件

・Aのインスタンス化は必ずBを経由して、mainでBをインスタンス化する形を取ります。
・できればAもBも手をつけずに感知したいです。

その他

スレッドで動かすことも考えましたが、負荷がかかると思いやっていません。
手段がなければそれでどうにかします。

以上です

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

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

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

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

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

fuzzball

2018/09/19 04:26 編集

「宣言」って何でしょうか?インスタンスの生成ってことですか?あと、スレッドを使えば出来るアテがあるということでしょうか?その場合、methodAの実行はどうやって検知するつもりなのでしょうか?
sponge_yukari

2018/09/19 06:43

申し訳ありません、別言語の名残で「宣言」と書いてました。Pythonではインスタンスの生成が正しいのですね。修正しておきます。 スレッドを使う場合、スレッドでクラス自体を監視して数値の変化があればそれでそのメソッドが使われたと判断する予定でした。Aのソースを簡略化しちゃったので肝心の数値は書いてませんね・・・。
fuzzball

2018/09/19 06:56

ということは、メソッド(methodA)の監視ではなく変数の監視ということでしょうか?(その変数はmethodAでしか触らないということ?)
sponge_yukari

2018/09/19 07:10

できることならメソッドの監視、できないのならそのメソッドで関係する変数の監視 と考えています。 そうですね、変数はmethodAでのみ変更します。
guest

回答5

0

典型的な「Observerパターン」で実装できます。

同じキーワードで検索すると優良記事がたくさんあるので参考にしてください。

適当に検索一位をはってみます。
https://qiita.com/nirperm/items/60ebc707bf35a836f637


考え方としては、あらかじめ連動する関数のポインタを獲得しておけば、自分が呼び出されるたびについでに連動すべき関数をコールする、というものです。


普通AやBでObserverとSubjectを継承すればよいです。
notifyを実装する必要がある気がしますが。

投稿2018/09/19 09:02

編集2018/09/19 09:09
mkgrei

総合スコア8560

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

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

0

ModelからViewに通知したいという要件として認識しました。

Eventを発火させる部分はデコレータでもう少し簡単に記述できそうですが。
こんな感じのコードでどうでしょうか。

Python

1# -*- coding: utf-8 -*- 2from copy import deepcopy 3from inspect import currentframe 4from pprint import pformat 5 6 7class EventHandler(object): 8 def __init__(self): 9 self._observers = [] 10 11 def append(self, listener): 12 """ 13 Listenerの追加 14 :param listener: 15 :return: 16 """ 17 assert listener is not None 18 if listener not in self._observers: 19 self._observers.append(listener) 20 return self 21 22 def remove(self, listener): 23 """ 24 Listenerの削除 25 :param listener: 26 :return: 27 """ 28 self._observers.remove(listener) 29 return self 30 31 def fire(self, sender: str, new_value): 32 for callback in self._observers: 33 callback(sender, new_value) 34 35 def __iadd__(self, other): 36 return self.append(other) 37 38 def __isub__(self, other): 39 return self.remove(other) 40 41 42class Model(object): 43 """ 44 モデル 45 """ 46 def __init__(self): 47 self.handler = EventHandler() 48 self._TopMost = True 49 self._ForeColor = "#000000" 50 self._BackColor = "#000000" 51 52 @property 53 def top_most(self) -> bool: 54 return self._TopMost 55 56 @top_most.setter 57 def top_most(self, value: bool) -> None: 58 self._TopMost = value 59 self.handler.fire(currentframe().f_code.co_name, value) 60 61 @property 62 def fore_color(self) -> str: 63 return self._ForeColor 64 65 @fore_color.setter 66 def fore_color(self, value: str) -> None: 67 self._ForeColor = value 68 self.handler.fire(currentframe().f_code.co_name, value) 69 70 @property 71 def back_color(self) -> str: 72 return self._BackColor 73 74 @back_color.setter 75 def back_color(self, value: str) -> None: 76 self._BackColor = value 77 self.handler.fire(currentframe().f_code.co_name, value) 78 79 def __deepcopy__(self, memo): 80 cls = self.__class__ 81 result = cls.__new__(cls) 82 memo[id(self)] = result 83 for k, v in self.__dict__.items(): 84 setattr(result, k, deepcopy(v, memo)) 85 return result 86 87 def __repr__(self): 88 return pformat(vars(self), indent=4, width=1) 89 90 91def changed(sender, val): 92 print(sender, val) 93 94 95def main(): 96 """ 97 エントリーポイント 98 """ 99 model = Model() 100 model.handler += changed 101 print(model) 102 print("#" * 60) 103 model.top_most = False 104 model.fore_color = "#AAAAAA" 105 print(model) 106 107if __name__ == '__main__': 108 main() 109

■参考情報

投稿2018/09/20 12:58

編集2018/09/20 17:57
umyu

総合スコア5846

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

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

0

Pythonはやっておらず、あまりdesign-patternにも詳しくはない ( 趣味でやっているので ) のですが、
確かデザインパターンのどれかに質問者さんがやりたいとおっしゃっている処理をサポートしている
ものがあった気がします。

たぶん、デザインパターン習得編 通りなら
Observerパターンだと思いますが。
それかMediatorパターン辺り。

これをPython向けの解説を探してみて...とかはどうでしょうか?

投稿2018/09/19 03:58

BeatStar

総合スコア4958

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

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

0

内部の実装によっては出来ない場合もあるかもしれませんが、Main から methodA を参照できるのであれば、methodA を関数でラップするのはどうでしょうか。つまり、デコレータを動的に適用します。

Python

1class A: 2 def __init__(self): 3 self.value = 0 4 def methodA(self): 5 self.value += 1 6 print(f'methodA: {self.value}') 7 8class B: 9 def __init__(self): 10 self.a = A() 11 def exec(self): 12 self.a.methodA() 13 14class Main: 15 def __init__(self): 16 self.b = B() 17 18 def wrap(func): 19 def _wrap(*args, **kwargs): 20 result = func(*args, **kwargs) 21 self.process() 22 return result 23 return _wrap 24 25 self.b.a.methodA = wrap(self.b.a.methodA) 26 27 def process(self): 28 print(f'process: {self.b.a.value}') 29 30main = Main() 31main.b.exec() 32 33# methodA: 1 34# process: 1

投稿2018/09/21 16:14

copepoda

総合スコア324

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

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

0

Aを継承したラップクラスを作って、methodAをオーバーライドして、その中でprocessを呼ぶ(実行する)ようにすれば出来るような出来ないような。(Bも同様にラップしたりする必要があるでしょう)

これで出来るならAとBそのものには手を加えなくて済みます。

投稿2018/09/19 07:22

fuzzball

総合スコア16731

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問