2016/11/17

[py]外部変数と同じ名前のglobalではない変数がある場合、書込みを行うとローカル変数ができる

まだまだpythonはわからないことだらけ。。。

いま、pyファイルにべたっと処理を書いているので、少しずつ関数化させている。
ライブラリのような形ではなく、ファイルをモジュールと見なして、中で値を持つような作りにしている。
後で不都合が出そうだが、そういうのも含めて勉強だ。

 

DB_NAME = 'db_all.db'
sql = 'CREATE TABLE IF NOT EXISTS clients(filename TEXT, owner TEXT)'


def create_db():
    conn = sqlite3.connect(DB_NAME)
    cur = conn.cursor()
    cur.execute(sql)     ...

SQL文を変数にする理由はないし、関数外に置く理由はさらにないのだが、ちょっと外に置いてみた。
そうすると、一番最後の「sql」でpyCharmがエラーを出している。
Unsolved referenceとのこと。

私の理解では、

  • 関数の外に置いた変数は、グローバル変数
  • 関数内で値を変更したかったらglobal指示するけど、参照だけなら気にせずできる

だったのだが、そうではないのか?
pyCharmが強い警告の意味で表示させているのかと思ったが、実行させるとエラーだった。

でも、ファイル名のDB_NAMEはエラーになっていない。。
試しにsqlをSQLにすると、これだけでエラーにならない。
慣習じゃなくて、言語として大文字かどうかを判定しているのか??

 

が、実は上のコードには続きがもう少しある。

DB_NAME = 'db_all.db'
sql = 'CREATE TABLE IF NOT EXISTS clients(filename TEXT, owner TEXT)'


def create_db():
    conn = sqlite3.connect(DB_NAME)
    cur = conn.cursor()
    cur.execute(sql)

    sql = 'SELECT * FROM clients WHERE filename=?'
    cur.execute(sql, ('file1.txt',))     ...

この後ろに、さらに同じ名前の変数に代入する処理があったのだ。
そちらがあるために、その前にあるsqlはグローバル側のsqlを参照できなくなったようなのだ。
試しに、グローバル側をsql2にして、さっきエラーになったところもsql2にすると、エラーが出なくなった。
そういうものなんだ。。。

 

9. クラス — Python 2.7.x ドキュメント

ここに記載があった。
今回の場合では、グローバル側に同じ変数名sqlがあって読み出し専用になるのだけど、その後ろにsqlへの書込みがあるため内側のスコープで新しいローカル変数sqlを作ることになり、結果としてその前にあるsqlもローカル変数のsqlとして見られるようになり、初出場で参照しようとすることになってエラー、という流れだろう。

インタプリタだから上から順に見ていくのかと思ったけど、この動作からするとファイルを一度読んで構築するか、少なくとも関数レベルでは一度に構築しているのだろう。
順番は大切、ということだ。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。