mayogohan
@mayogohan

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

tkinterを用いた電卓作成時の不具合について

下記コード def clear():においてなぜglobal宣言が必要なのでしょうか?

現在加算のみ可能な電卓を引用先の資料を参考にしながらtkinterを用いて作成しているのですが、一点不明な所があります。def clear():においてなぜglobal宣言をすることが必要なのでしょうか?他のdef key(n):などにおいてグローバル宣言をするのはプログラム冒頭で定義したcurrent_numberやfirst_termと競合(current_numberの値が2つある状況)を回避するためにも必要なのは理解できるのですが、def clear():の場合current_numberの値は0であり、同じ変数に複数の値があるという状況は生まれないように思われます。しかし、それでもgulobal宣言を消去すると、値を消去することができません。私の脳内では、

current_number=1が存在する

def clear()を実行する

この時、冒頭で定義したcurrent_number=0を関数内に再び記述し、current_numberの値を1から0にする

これで十分なのでは?

となっております。

どなたかご教授いただけますと幸いです。
引用元:https://repository.kulib.kyoto-u.ac.jp/dspace/bitstream/2433/285599/1/Version2023_10_17_01.pdf

発生している問題・エラー

import tkinter as tk

current_number = 0
first_term = 0
second_term = 0
result = 0

def do_plus():
    global current_number
    global first_term

    first_term = current_number
    current_number = 0

def do_eq():
    global second_term
    global result
    global current_number
    second_term = current_number
    result = first_term + second_term
    current_number = 0

def key(n):
    global current_number
    current_number = current_number * 10 + n
    show_number(current_number)

def clear():
  #ここがわかりません↓
    global current_number
    current_number = 0
    show_number(current_number)

def plus():
    do_plus()
    show_number(current_number)

def eq():
    do_eq()
    show_number(result)

def show_number(num):
    e.delete(0,tk.END)
    e.insert(0,str(num))

root = tk.Tk()
f = tk.Frame(root)
f.grid()

b1 = tk.Button(f,text="1", command=lambda:key(1))
b2 = tk.Button(f,text="2", command= lambda:key(2))
b3 = tk.Button(f,text="3", command=lambda:key(3))
b4 = tk.Button(f,text="4", command=lambda:key(4))
b5 = tk.Button(f,text="5", command=lambda:key(5))
b6 = tk.Button(f,text="6", command=lambda:key(6))
b7 = tk.Button(f,text="7", command=lambda:key(7))
b8 = tk.Button(f,text="8", command=lambda:key(8))
b9 = tk.Button(f,text="9", command=lambda:key(9))
b0 = tk.Button(f,text="0", command=lambda:key(0))
bc = tk.Button(f,text="C", command=clear)
bp = tk.Button(f,text="+", command=plus)
be = tk.Button(f,text="=", command= eq)

b1.grid(row=3,column=0)
b2.grid(row=3,column=1)
b3.grid(row=3,column=2)
b4.grid(row=2,column=0)
b5.grid(row=2,column=1)
b6.grid(row=2,column=2)
b7.grid(row=1,column=0)
b8.grid(row=1,column=1)
b9.grid(row=1,column=2)
b0.grid(row=4,column=0)
bc.grid(row=1,column=3)
be.grid(row=4,column=3)
bp.grid(row=2,column=3)

e = tk.Entry(f)
e.grid(row=0,column=0,columnspan=4)
clear()

root.mainloop()
0

3Answer

Python では関数内の変数は以下のように扱います.コラム「変数のスコープ」も参
照してください.
 ローカル変数:関数内で定義された(代入された)変数は関数内でのみ利用可
能で,関数の(毎回の)実行ごとに関数の実行が終了すれば失われます.
 仮引数もローカル変数として扱われます.
 グローバル変数:関数外で定義されている変数は値を読み取ることのみ可能で
す.
 グルーバル変数への代入:関数内で global 宣言された変数のみ,グローバル変
数に代入可能です.
Python で関数内の変数をこのように扱うことにより
 関数内で一時的に必要な変数は他への影響を考えずに自由に使えます.
 グローバル変数の操作はプログラムが長くなるとプログラムを分かりにくくす
る要因になるのですが,Python では比較的安全な読み取りは無条件で許可する
一方で,書き込みは global 宣言でプログラムに明示することを求め安全性と利
便性のバランスをとっています.

とのことです

つまりdef clear()内で定義されたcurrent_numberは冒頭で定義したものとは別物です。
冒頭で定義したcurrent_numberに再代入を行うにはglobal宣言が必要になります

0Like

失念しておりました、、申し訳ありません、、ご回答ありがとうございました。

0Like

Your answer might help someone💌