長いコードでは気が狂います。Pythonは引数を用いなくても関数の外の値を参照できますが、きちんと引数を使ったり、コード内にコメントで残しておくなど、関数への入出力を明確にする工夫をしないと大変だと思います。どの変数がどの範囲まで影響をあたえるか、スコープを知っておくことは関数を使うときの必須事項です。Pythonって、できるだけ型宣言はしない方針の言語ですよね。コードの行数も減るし、使いやすいですが、その分、仕様を頭にたたきこんでおかないと、思わぬ事故が起こります。私が実際に購入した教材のご紹介0.チュートリアル学習のポイントシリーズこの記事は「Pythonチュートリアルのポイント整理シリーズ」の記事です。一連の記事は、以下のリンク集を参照してください。「Pythonチュートリアル」のポイント整理シリーズ1.スコープとはスコープとは、コード内での変数の有効範囲のことです。Pythonには以下の4つのスコープがあります。(書籍とかを読んでも、参照する関数側から見たスコープと、変数を宣言した側からみたスコープの説明が混在していて、わかりにくいんですよね~。scope)関数の内側で宣言された変数は「ローカル変数」といいます。このローカル変数のスコープを「ローカルスコープ」といいます。ローカルスコープは、変数の宣言を行った関数の内側です。関数の外側からは関数の内側の変数を参照することはできませんので、外側はローカルスコープの範囲外です。関数が入れ子構造になっている場合、変数が定義された位置よりも外側の関数からはその変数を参照できませんが、内側の関数からはその変数を参照することが可能です。定義された変数の位置よりも内側にある関数の中もローカルスコープに含まれます。scope)「外側の関数のスコープ」は、関数が入れ子の構造(ネスト)になっている場合を想定しています。このとき、内側の関数から見て、外側の関数でローカル変数が定義されているときに、その外側の関数のローカル変数のスコープを「外側の関数のスコープ」といいます。ここで重要なのは内側の関数から外側の関数のスコープを見ている点です。視点が変わっているだけなので、難しく考える必要はありません。スコープの優先順位の説明をするときなど、この用語を使うと便利な場合があります。グローバル変数については、関数から見て外側で定義されていますが、関数で定義されたローカル変数ではないので「外側の関数のスコープ」の対象になりません。Scope)モジュール(Pythonのファイル「ファイル名.py」に記されたコード全体のこと)のトップレベル(全ての関数やクラスの外側)で宣言された変数をグローバル変数といいます。このグローバル変数のスコープを「グローバルスコープ」といいます。「グローバルスコープ」はモジュール全体です。グローバル変数は、モジュールの中なら、どこからでも参照することができます。)「ビルトインスコープ」とは、組み込み関数や組み込み変数のスコープです。組み込みであるため、変数や関数を宣言する必要はありません。ビルトインスコープはプログラム全体です。Pythonを起動した時点で、どのモジュールからでも呼び出すことが可能です。それぞれのスコープが重なった時の優先順位は「ローカルスコープ」「外側の関数のスコープ」「グローバルスコープ」「ビルトインスコープ」です。「外側の関数」が複数ある場合は内側の関数の方が優先順位が高いです。(「外側の関数のスコープ」という言葉が無いと、このような説明が大変になります。)関数の外側の変数を参照することは可能ですが、関数の外から関数の内側の変数を参照することはできません。nonlocalを用いて定義された変数は例外です。関数の外側の変数を参照できるのは、外側から内側の関数に「参照渡し」をされているためです。したがって、変更不能体(イミュータブル)の変更(例:b=2)は、外側の関数に影響しません。リストの様な変更可能体(ミュータブル)の要素の変更(例:b[0]=2)は、外側の関数に影響を与えます。要素の変更ではなく、変数に変更可能体を再代入(例:b=[2])した場合は、変更可能体であっても外側の関数に影響しません。具体的な例示でなければ分かりにくいと思いますので、サンプルコードによる説明を行います。3層以上の入れ子構造(ネスト)になっている例や、関数が並列で並べられているような例は少ないので、参考になるのではないでしょうか。説明で使用するサンプルコード以下のコード01を用いてスコープの説明をしたいと思います。実行してもなにも出力されないまったく意味のないコードですが、できるだけシンプルにするために、よけいなコードは省略しました。xxx3()は、それぞれ、入れ子構造(ネスト)になっており、関数xxx1()の中で関数xxx2()が定義されており、さらに関数xxx2()の中で関数xxx3()が定義されています。xxx3()は、それぞれ定義された直後に実行されています。関数yyy1()は関数xxx3()の中で実行されています。y1は、それぞれのスコープが様々な形で重なるように配置しています。xxx1()なお、スコープの説明からは少し脱線しますが、コード01の関数の定義の位置とその関数を実行する位置の関係について簡単に説明します。コード01の16~17行目で定義された関数yyy1()は、それよりも前の行の12行目で実行することできます。これは、21行目でxxx1()が実行された時にはすでにyyy1()が、定義されているからです。7~13行目の関数xxx2()を、例えば6行目と7行目の間で実行しようとしても実行できません。これは、例えばローカル変数をprint()で出力するときに、出力するローカル変数を定義したあとでprint()文を実行しなければならないのと似ています。入れ子構造の内側の関数は、関数の定義行より後の行で実行しましょう。下図は上記のコード01について、スコープの範囲と、スコープが重なっている場合の優先順位を示したものです。大きな図ですが、コード01のそれぞれのスコープについて説明します。今度は、更に具体的に、それぞれの関数の中でどの変数を参照することができるかを図に書き込みました。こちらの方が具体的でわかりやすいという人もいると思います。どこからでも参照することができるビルトインスコープは図から外しました。最後に、それぞれの関数の中でどの関数を参照することができるかを図に書き込みました。こちらもビルトインスコープは図から外しました。変数の場合と同じルールで優先順位がつけられていることがわかります。同名の関数についてまず、入れ子構造(ネスト)の関数同士の名前が同じでもエラーにはなりません。バグの原因となるので、同じ名前にするのは避けましょう。コード03のように一番上の階層に定義された関数同士の名前が同じ場合も、エラーにはなりません。この時、先に読み込まれた関数は、後述の関数に上書きされるようですので、同じ名前の関数を用意する意味がありません。引数が違う同名の関数も別の関数とは扱われません。こと、エラーにしてくれた方がよいと思うのですが、どうなんでしょう。私の知らない有用な使い方があるのでしょうか・・・。コード02は、同じ名前の関数xxx()を並べた例です。エラーは生じていません。後ろの関数の「ティラミス」が出力されました。print('ティラミス')xxx()#出力02ティラミス次に、コード03では、イチゴショートとティラミスの関数を逆にしてみます。すると、出力も逆になりました。print('イチゴショート')xxx()#出力03イチゴショートでは、引数の数が違う同名の関数ではどうでしょうか。引数が違うため、同名でも違う関数として扱われるのでしょうか。検証してみると次のようになります。コード04は、実行可能ですが、コード05はエラーとなります。引数の数を変えても違う関数とはみなされず、後で記述した方の関数に上書きされるようです。うっかり間違える(?)例題コード06はyyy()の内側にxxx()がある「入れ子構造の関数」ですが、コード07は、xxx()とyyy()は、互いに入れ子構造にはなっていません。どちらも、関数yyy()の中でxxx()を呼び出しています。10というコードを挿入してみました。コード08では、入れ子構造の関数なので、yyy()のローカル変数の値がxxx()に影響を与え、4行目の出力は10になります。コード09のように、関数yyy()から関数xxx()を呼び出す場合、入れ子構造ではないxxx()の中の変数に影響を与えることはありませんので出力は1のままです。これは、関数のスコープの基本的な内容なので、慣れている人にはあたりまえのことかもしれませんが、ついつい混同してしまいますので気をつけましょう。1ではなく、10が出力。10ではなく、1が出力。入れ子構造の内側から呼び出した場合のreturnせっかくですので、入れ子構造の内側から外側の関数を呼び出した場合のreturnの働きについて調べてみます。ここで重要なのは、「returnは関数を抜ける」とだけ覚えるのではなく、「returnは関数を抜け、関数を最後に呼び出した位置にもどる」と覚えた方がよいことです。入れ子構造の関数の内側から外側の関数を呼び出す方法を使うケースは多くないと思いますので、さっと目を通して難しいようでしたら、ここから後は読み飛ばしてください。コード10のリストtmpは変更可能体(ミュータブル)ですので、9行目の要素の変更はこのコードのtmp全てに影響を与えます。1になると、xxx1()は5~7行目のreturnにより13行目のxxx2を呼び出すコードが実行されることなく終了します。5~7行目のコードがなければ、11行目のxxx1を呼び出すコードと13行目のxxx2を呼び出すコードが交互に実行され、無限ループになり、「xxx1-start」と「xxx2-start」が延々と出力されます。入れ子構造の内側から外側の関数を呼び出す場合には、注意深くコーディングする必要があります。コード10は7行目のreturunの実行により、どの位置にもどるのかを検証するためのサンプルコードです。print('xxx1-end')xxx1()print('end')#出力10xxx1-startxxx2-startxxx1-startreturn発動xxx2-endxxx1-endendそれでは、迷路のようなコード10の実行順序を図示してみます。15行目「2xxx1の1回目の呼出」では、tmp[0]=0なので、5~7行目のコードは実行されません。7行目のreturnが実行されるのは11行目「6xxx1の2回目の呼出」により、関数xxx1が実行されたときです。このコードでは7行目のreturn実行後は関数を抜けて15行目にもどるのではなく、最後にxxx1を呼び出した11行目にもどります。先ほど「returnは関数を抜ける」とだけ覚えるのではなく、「returnは関数を抜け、関数を最後に呼び出した位置にもどる」と覚えた方がよいと言ったのはこのことです。おまけ記事:検証コード(同じ名前の関数の呼び出し)以下、名前が同じ関数がある場合に、どの関数が優先的に読み込まれるのかを検証したコードです。記事の内容を検証するために作成したコードであり、だらだらと長く読みにくいです。実際のコードを用いて自分でも検証したい方だけ参考にしてください。関数名が全て異なる例コード11は関数名が全て異なる例です。xxx3()が入れ子になっており、最も内側の関数xxx3(13行目)の中の18行目から一番外側のxxx1(3行目)を呼び出しています。0→1とし、2回目以降の関数の実行はreturnですぐにもどってくるようにしているため、無限ループにはならないようになっています。内側の関数xxx3()から外側の関数xxx1()を呼び出すことができました。説明が繰り返しになりますが、「returnは関数を抜ける」とだけ覚えるのではなく、「returnは関数を抜け、関数を最後に呼び出した位置にもどる」と認識することにより、コードが理解しやすくなります。理解できている人には当たり前のことかもしれませんが、7行目のreturnは28行目の位置にもどるのではなく、関数xxx1を最後に呼び出した18行目にもどります。1番外側と、外から2番目の関数の名前が同じ場合コード12は、コード07においてxxx2()となっていた関数名をxxx1()に変更しました。したがって、xxx1()という関数名が2つ存在します。内側のxxx3()の18行目でxxx1()を呼び出していますが、より内側の8行目のxxx1()の方が呼び出されていることがわかります。22行目のxxx1()の呼び出しにおいて、3行目ではなく8行目のxxx1()が呼び出されていることもわかります。xxx3()の名前をxxx1()に変更し、入れ子構造になっている部分の関数名を全てxxx1()にしました。入れ子構造の関数では、同じ名前の関数がある場合、例えば22行目のxxx1()では、同じ関数内にある8行目のxxx1()を優先しています。18行目のように同じ関数内にxxx1()がなければ、外側の関数を近いほう(13行目)から順番に探していることがわかります。13行目)だけではなく、入れ子構造の外側(23行目)にも同じ名前の関数があるケースです。18行目のyyy1()の呼び出しに対して、23行目ではなく、13行目が呼び出されています。上の階層の関数名が同じ場合なお、コード15では優先順位を検証する以前に、3行目の関数xxx1()は、その後に記述された23行目のxxx1()によって、上書きされているため、27行目のxxx1()の呼び出しに対して23行目の関数が呼び出され、出力15のような結果となります。xxx1()#出力15yyy1いかがでしょうか。この記事は、どんな風に書けばよいのか悩みました。重要な内容でありながら、色々なケースが考えられます。記事を読まれた方に1つでも役にたつ内容があればうれしいです。以下、私が実際に購入したPythonの教材をまとめてみました。Pythonを学習する上で、少しでもお役に立つことができればうれしいです。June関連記事PythonPythonとは何?Pythonと他の言語の比較は、ネット上にあふれているので、ここには書きません。私はExcelとVBAが大好きなのです。プログラムでお金を稼いでいるわけではないので、これで十分。Excelはとにかく入出力が楽。入力データの加...PythonPython♪基本:簡単なfor文とrandom関数を使ってグラフを表示しようif文もfor文も配列も関数も知らない状況で、なにからPythonを説明するのがいいのでしょう。Wolrdの出力が面白いのは最初の1度きりです。プログラミングの家庭教師って、思ったよりも難しい...PythonPython♪基本:Pythonのインデントと命令文の影響範囲Pythonでは、プログラムの命令文の実行の順序や影響範囲を示すのに「インデント」を使います。「インデント」とは文のはじめの空白のことです。Pythonでは、繰り返し計算の命令文であるfor文や、条件分岐の命令文であるif文の影響範囲を「...PythonPython♪NumPyの「参照渡し」と「コピー」を覚えよう。リストの「参照渡し」「浅いコピー」「深いコピー」とNumPyの配列の「参照渡し」「コピー」とは、コンピューターの内部でのメモリーの扱いも実行のしかたも全然違います。これを混同してしまうと大変なことになります。ここでは、NumPyの配列の...PythonPython♪Pythonチュートリアルとはどんな書籍なのか「Pythonチュートリアル」を検索すると、「基本的な内容が勉強できる」「良い本である」「初心者がいきなり読むのは難しい」「Pythonの資格の出題範囲」といった内容がヒットします。よい本だけど、基本的な本なのに、初心者には難しい?そこで...PythonPython♪FEM:平面トラスの有限要素法サンプルコード平面トラスの有限要素法のプログラムをPythonで組んでみました。以前に自分がつくったコードを引っ張り出してきて、Pythonに移植しました。このくらいのボリュームのプログラムにじっくり取り組むと面白いですね。Python♪NumPyの「参照渡し」と「コピー」を覚えよう。Studioが遅いときの対策2020.01.11Kotlin♪環境設定「HAXMがインストールされていません」2020.01.052020.01.08Python♪FEM:部材座標系の要素剛性マトリクス2020.01.04Kotlin♪スマホアプリの言語は、Kotlin、Java、C#、Dart?2020.01.012020.01.13スポンサーリンクスポンサーリンク。