C言語プログラマがPythonのお勉強で気になったことメモ(その3)

前回からの続きです。 stacked-tip.hateblo.jp

3章で気になって調べたこと

ipywidgetsのobserve()

ipywidgetsに含まれるウィジェットobserve()というメソッドを持っています。 これは、ウィジェットが変化したときに実行するコールバック関数を登録することができるメソッドです。

テキストでは

dropdown.observe(order_by_store, names='value')

と書いてありますが、これはこの直前に定義したorder_by_store()関数をコールバック関数として登録しているのです。 なお、第2引数のnames='value'は、コールバック関数の引数として渡すものを名前で指定しています。 上記の例ではvalueをいう文字列を渡していますが、これは、dropdownの属性であるvalueを渡す、という意味です。

dropdownの属性であるvalueは、dropdownに関する情報を持っているリストです。具体的には

  • name:名前
  • old:変更前の値
  • new:変更後の値
  • owner:ウィジェット(今回の場合はdropdown)自身の情報
  • type:イベント発生条件

が入っています。

テキストの例にあるorder_by_store関数の中で、

clear_output()
print(val)

のようにclear_output()の後でvalを表示してみると、具体的な中身が見えます。 f:id:stacked-tip:20220103163255p:plain

order_by_store関数の中で

pick_data = order_data.loc[(order_data['store_name']==val['new']) & (order_data['status'].isin([1,2]))]

と書いていますが、ここのval['new']とは変更後の値を指しています。


Pythonグローバル変数・ローカル変数

#(前略)
def order_by_multi(val):
  clear_output()
  display(select)
  pick_data = order_data.loc[(order_data['store_name'].isin(val['new'])) & (order_data['status'].isin([1,2]))]
  display(pick_data.head())

select = SelectMultiple(options=store_list)
#(後略)

上のようなコードがテキストにありますが、ここで

  display(select)

selectは、関数定義の外にある

select = SelectMultiple(options=store_list)

グローバル変数selectを指しています。

Pythonには、グローバル変数とローカル変数以外に「フリー変数」なる変数があるようです。 公式ドキュメントに"free variable"と書かれているものがそれです。 docs.python.org

この「フリー変数」ですが、公式ドキュメントを読んでもいまひとつ挙動がわからない。 Qiitaの記事等を参考にすると、どうやら、

  • ブロックの外にある変数と同名の変数をブロックの中で読み込む→ブロックの中の変数はグローバル変数として扱われる
  • ブロックの外にある変数と同名の変数にブロックの中で書き込む→ブロックの中の変数は同名で別のローカル変数として扱われる

という挙動のようです。

qiita.com

少し例を挙げます。

例1

def func():
  print(hoge)

hoge = 1
print(hoge)
func()
print(hoge)

これの結果は

1
1
1

です。

例2

def func():
  hoge = 2
  print(hoge)

hoge = 1
print(hoge)
func()
print(hoge)

これの結果は

1
2
1

となります。

例3

def func():
  print(hoge)
  hoge = 2
  print(hoge)

hoge = 1
print(hoge)
func()
print(hoge)

これの結果はエラーになります。

1

---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-11-532135ee2a15> in ()
6 hoge = 1
7 print(hoge)
----> 8 func()
9 print(hoge)

<ipython-input-11-532135ee2a15> in func()
1 def func():
----> 2 print(hoge)
3 hoge = 2
4 print(hoge)
5

UnboundLocalError: local variable 'hoge' referenced before assignment