43267


初歩的なことなのですが、`global`変数に関する問題です。

[code]

    from PySide import QtGui
    import sys
    
    class GlobalTest(QtGui.QTextEdit):
        def __init__(self,parent=None):
            super(GlobalTest,self).__init__(parent=None)
    
        def closeEvent(self,event):
            if g_is_modified == True:
                message = QtGui.QMessageBox().warning(None,"Warning-警告","書き換えられた内容があります。このまま閉じてもよろしいですか？\n",QtGui.QMessageBox.Ok,QtGui.QMessageBox.Cancel)
                if message == QtGui.QMessageBox.Ok:
                    pass
                else:
                    return
            print(15,global_widget.parent() == self)
            return QtGui.QTextEdit.closeEvent(self,event)
        def focusInEvent(self,event):
            print("focus ｷﾀ")
            global g_is_modified
            g_is_modified = True
            global_widget.setParent(self)
            return QtGui.QTextEdit.focusInEvent(self,event)
    def main():
    
        try:
            QtGui.QApplication([])
        except Exception as e:
            print(19,e)
        global g_is_modified
        g_is_modified = False
        global global_widget
        global_widget = QtGui.QWidget()
        glob = GlobalTest()
        glob.show()
    
        sys.exit(QtGui.QApplication.exec_())
    if __name__ == "__main__":
        main()
    
[/code]

`main()`関数内で、一度、`global`宣言をし、`g_is_modified = False`を入れ込んでいます。  
この変数の値は、`focusInEvent`に入った時に、上書きされるようにしています。  
一方で、もう一つ、`global`宣言をし、次は、`global`ウィジェットをグローバル化しています。同様に、このウィジェットの親を、`focusInEvent`に入った時に`GlobalTest`に設定しています。  
結果は、

[code]

    15 True
    16 True
    
[/code]

で問題ありません。これは、解決後の問題です。(最初はなぜ上書きできないのだろうということが疑問でしたが、どちらでもglobal宣言をしたらOKでした。)  
解決前は、`focusInEvent`内では、`global`宣言をしておりませんでした。

[code]

    def focusInEvent(self,event):
        print("focus ｷﾀ")
    
        g_is_modified = True
        global_widget.setParent(self)
        return QtGui.QTextEdit.focusInEvent(self,event)
    
[/code]

結果

[code]

    15 False
    16 True
    
[/code]

`g_is_modified`の値は上書きされませんでした。

`g_is_modified`は、再度`global`宣言をしなければ値が上書きされることはありませんが、`widget`は、一度`global`宣言をすれば、値が更新されました。この違いはなんでしょうか？単なる変数と、クラスの一メソッドなので、全くの別物のため、なんとなく理由はわかりますが、わかりやすく説明していただくことは出来ますか？


CC BY-SA 3.0
2018-04-15T06:17:22.417
43254
2018-04-15T13:19:04.973
2018-04-15T06:23:31.020
24284
24284
question
python qt pyqt pyside
global宣言は一度だけすればいいというものではないのか


Pythonでは、代入をおこなうとローカルスコープになります。

g_is_modified は、代入がされているのでglobal文がなければlocal変数になり、global_widget
の方は代入されていないのでglobal変数が使われます。

公式のチュートリアルだと以下のように説明されています。

<https://docs.python.jp/3/tutorial/classes.html?highlight=%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97>

> Python 特有の癖として、代入を行うと – どの global 文も有効でない場合は –
> 名前がいつも最も内側のスコープに入るというものがあります。代入はデータのコピーを行いません — 単に名前をオブジェクトに結びつける (bind)
> だけです。オブジェクトの削除でも同じです: del x は、 x
> をローカルスコープが参照している名前空間から削除します。実際、新たな名前を導入する操作は全てローカルスコープを用います。とりわけ、 import
> 文や関数定義は、モジュールや関数の名前をローカルスコープに結び付けます。


CC BY-SA 3.0
2018-04-15T13:19:04.973
43267
2018-04-15T13:19:04.973
15171
43254
answer