42932


やりたい事はタイトルのままなのですが、具体的には

[code]

    @printの割り込み処理
    def interrupt():
        print('割り込み処理')
    
    # あるいは
    @割り込み処理
    def interrupt():
        if __割り込み元を持っているもの__ == print:
            print('割り込み処理')
    
    print('通常出力')
    
    # 出力
    割り込み処理
    通常出力
    
[/code]

みたいな事ができれば良いのですが、上記のような事は出来ますでしょうか？  
例ではprintとしていますが、printに限りません。  
なお、python3系です。

出来なければ出来ない、という回答がいただけると助かります。  
出来ない場合、どういう工夫でそれっぽい事が出来るのか、アイデアをもらえるとそれはそれ嬉しいです。

例えば

[code]

    INTERRUPT = True
    
    @ユーザー関数のprint
    def user_print(message, interrupt_flag=INTERRUPT)
        if interrupt_flag:
            interrupt()
        print(message)
    
[/code]

みたいな方法になるのかな、と漠然と考えています。


CC BY-SA 3.0
2018-04-04T02:52:28.783
42919
2018-04-04T15:08:29.930
2018-04-04T05:26:14.423
19110
27817
question
python python3
python3 標準関数に割り込み処理を入れたい


[Python でイベント指向のプログラミングを実現する](https://emptypage.jp/notes/pyevent.html)
の記事に書かれている事が、質問者が希望している事ではありませんか？


CC BY-SA 3.0
2018-04-04T04:51:38.917
42923
2018-04-04T04:51:38.917
217
42919
answer


以下は`print`を自前の関数に置き換え、元の組込み`print`の実行前にメッセージを出す例です。

### [builtins](https://docs.python.org/ja/3/library/builtins.html)
経由での全体的な置き換え

[builtins](https://docs.python.org/ja/3/library/builtins.html)モジュール経由で組み込みオブジェクトの名前空間を参照して、自前の関数に置き換える方法です。  
この操作を行なうファイルだけでなく、他のモジュールにも影響します。

[code]

    #!/usr/bin/python3
    # 本物の組込みprint関数の値を保存しておく
    orig_print = print
    
    # 自前のprint用関数を定義する
    def my_print(*args):
        orig_print("# カスタム版printが呼ばれました")   # 追加したい処理
        return orig_print(*args)   # 元のprintの呼び出し
    
    # トップレベル（組込み識別子の名前空間）のprintを自前のものにする
    import builtins
    builtins.print = my_print
    
    # このファイルでprintという変数は定義されていないので、
    # ここでのprintはトップレベル（組込み識別子の名前空間）のprintとなる
    # そして、それは上で置き換え済み
    print("hello, world")
    
[/code]

出力:

[code]

    # カスタム版printが呼ばれました
    hello, world
    
[/code]

### 現在のファイル（モジュール）で`print`を定義

Pythonでは、最初の代入で現在のローカル名前空間内の変数が作られることを利用し、`print`変数に自前の関数を代入してしまいます。  
この場合、トップレベル（組込み識別子の名前空間）の`print`はそのままですから、他のモジュールでの`print`の呼び出しには影響しません。

[code]

    print = my_print   # my_print の定義は上を参照
    print("hello, world")
    
[/code]

### 特定のモジュールの名前空間に `print` を追加

下のように、モジュールに`print`を追加してしまえば、そのモジュール内で`print`が呼び出された際には、これが呼ばれることになります。

[code]

    import module_a
    module_a.print = my_print   # my_print の定義は上を参照
    
[/code]

### その他

テストやデバッグ目的としては、[`unittest.mock`](https://docs.python.org/ja/dev/library/unittest.mock.html)モジュールも参考になるかと思います。


CC BY-SA 3.0
2018-04-04T15:06:45.337
42932
2018-04-04T15:06:45.337
3054
42919
answer


組み込み関数を上書きしたいというのであれば、[builtinsモジュール](https://docs.python.jp/3/library/builtins.html)を使ってください。

[code]

    # coding: utf-8
    
    import sys
    if sys.version_info.major < 3:
        import __builtin__ as builtins
    else:
        import builtins
    
    print_original = builtins.__dict__['print']
    def print_custom(s):
        print_original('Interrupt.')
        print_original(s)
    builtins.__dict__['print'] = print_custom
    
    print('Hello, world!')
    
[/code]

ただ、注意が必要です。

上書きしたprint関数でprintを呼びだせば、当然再帰的に関数が呼ばれる事になります。  
(上記の例では、そのためにオリジナルのprint関数を「print_original」に保存しています)

builtinsモジュールを変更すると、importしたモジュールにも影響を及ぼします。

他にこのようなソースコードは見かけないので、ある意味禁じ手なのかぁ…。

ちなみに、上記のソースコードは、python2では動きません。  
おそらく、printが関数ではなく文だからではないかと思いますが。


CC BY-SA 3.0
2018-04-04T15:08:29.930
42933
2018-04-04T15:08:29.930
15473
42919
answer