質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

3回答

932閲覧

スコープと名前空間について

Shingodate1

総合スコア4

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/06/17 00:27

pythonの名前空間について質問させて頂きます。
do_local()を呼び出した時に変数はdef scope_test()内の関数ということもありspam = "test spam"がかえってきているのは理解できるんですが、pythonはdefで関数ができるというところでdef do_localは関数ではないのでしょか?
お手数ですがご教授頂けたら幸いです。

python

1def scope_test(): 2 def do_local(): 3 spam = "local spam" 4 5 def do_nonlocal(): 6 nonlocal spam 7 spam = "nonlocal spam" 8 9 def do_global(): 10 global spam 11 spam = "global spam" 12 13 spam = "test spam" 14 15 do_local() 16 print("After local assignment:", spam) 17 18 do_nonlocal() 19 print("After nonlocal assignmennt:", spam) 20 21 do_global() 22 print("After global assignment:", spam) 23 24scope_test() 25print("In global scope:", spam) 26 27出力結果  28After local assignment: test spam 29After nonlocal assignmennt: nonlocal spam 30After global assignment: nonlocal spam 31In global scope: global spam

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

質問のコードの範囲で考えると"名前空間"は以下の2種類のものがでてきます。

  • モジュールのロードが開始された時にできる名前空間
  • 関数が実行された時にできる名前空間

これだと呼称が長いので、前者をグローバルな名前空間と呼んで、後者をローカルな名前空間と普段は呼んでます。

(もし対話環境で実行しているなら、前者は「対話環境が開始された時にできる名前空間」と思ってください)


def do_localは関数ではないのでしょか?

def do_localによって作られる関数は、scope_testの実行中def do_local文が実行されることで生成され、scope_testの終了すると、どこからも参照できなくなる関数オブジェクトです。


scope_testを定義するdef文を実行すると、関数オブジェクトができて「モジュールの名前空間」でscope_testという名前と結びつけられます。
scope_test(という名前に結びついている関数オブジェクト)を実行すると、本体が実行される前に「scope_test実行中の名前空間」が作られます。
def文が3つ実行されて、関数オブジェクトが3つできて「scope_test実行中の名前空間」でdo_local、do_nonlocal、do_global という名前と結びつけられます。
spam = "test spam"が実行されて「scope_test実行中の名前空間」でspamという名前が作られて、"test spamという文字列と結びつけられます。

この時点で「scope_test実行中の名前空間」には3つの関数があって、それらを順に実行していっています。
それぞれ、実行されている間「その関数を実行中の名前空間」ができます。

do_local関数を実行している間、「do_local実行中の名前空間」には名前spamがあって、代入文で"local spam"が結びつけられます。
do_nonlocal関数を実行している間、「do_nonlocal実行中の名前空間」には名前spamはありません。nonlocal文があることでdo_nonlocal関数の中の名前spamは「scope_test実行中の名前空間」を参照します。
do_global関数を実行している間、「do_global実行中の名前空間」には名前spamはありません。global文があることでdo_global関数の中の名前spamは「モジュールの名前空間」を参照します。

scope_test関数の本体に書いてあるprint文中の名前spamはすべて「scope_test実行中の名前空間」を参照します。

scope_test関数の実行が終わると「scope_test実行中の名前空間」は破棄されます。
「scope_test実行中の名前空間」が破棄されたことで、do_local、do_nonlocal、do_globalと結びついていた関数オブジェクトはもうどこからも参照できないオブジェクトになります。

最後に書いてあるprint文中の名前spamは「モジュールの名前空間」を参照します。

投稿2021/06/17 03:09

quickquip

総合スコア11038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shingodate1

2021/06/18 01:00

>do_local関数を実行している間、「do_local実行中の名前空間」には名前spamがあって、代入文で"local spam"が結びつけられます。 上記の文章について質問です。 scope_test実行中の名前空間でspamが"test spamという文字列に結びつけられるとありますが、上記の文章で代入文で"local spamが結びつけられるとあります。 ですがdo_localを実行すると"test spamが実行されるのはなぜでしょうか? "local spamが結びつけるというのは"test spamから"local spamに上書きされているという意味でしょうか?
quickquip

2021/06/18 01:52

「scope_test実行中の名前空間」と「do_local実行中の名前空間」は別のもので、したがって、 『「scope_test実行中の名前空間」の名前spam』と『「do_local実行中の名前空間」の名前spam』も別のもの ですよ。 分かっていなかったのはそのあたりですか? (確かに回答に明記してないですね……)
quickquip

2021/06/18 01:54

『「do_local実行中の名前空間」の名前spam』に値を結びつけることをしても、 『「scope_test実行中の名前空間」の名前spam』には影響を与えません。
Shingodate1

2021/06/18 02:24

回答を失礼致します。 >「scope_test実行中の名前空間」と「do_local実行中の名前空間」は別のもので、したがって、 『「scope_test実行中の名前空間」の名前spam』と『「do_local実行中の名前空間」の名前spam』も別のもの それではなぜdo_local実行中の名前空間を呼び出した時に、scope_test実行中の名前空間のspamが表示されるのでしょうか?
quickquip

2021/06/18 02:59

「do_local実行中の名前空間を呼び出した時」とありますが、 「名前空間を呼び出す」は意味が通らないです(=意図が伝わってないです)。どういう意図で言ってますか? コードのどこの部分のどんな作用を指してますか?
quickquip

2021/06/18 04:08 編集

spam = "test spam" # 『「scope_test実行中の名前空間」の名前spam』をセット do_local() # 「do_local実行中の名前空間」を作る + 『「do_local実行中の名前空間」の名前spam』 をセット(とprint) + 「do_local実行中の名前空間」の破棄 print("After local assignment:", spam) # 『「scope_test実行中の名前空間」の名前spam』をprint ですよ
quickquip

2021/06/18 03:07 編集

dolocal() すると 1. 新しい名前空間を作る 2. 関数の実行中保持する 3. 関数の実行が終わって、かつ他のオブジェクトからの参照がないなら破棄する という事が起こります。 この事象全体を踏まえた上で、ここで作られる名前空間を称して便宜上「do_local実行中の名前空間」と書いてます。
quickquip

2021/06/18 03:17

名前空間とはなにか? から始めた方がよかったでしょうか?
Shingodate1

2021/06/18 03:19

>「scope_test実行中の名前空間」と「do_local実行中の名前空間」は別のもので、したがって、 『「scope_test実行中の名前空間」の名前spam』と『「do_local実行中の名前空間」の名前spam』も別のもの こちらの文章のことを申しあげていました。 2個目のコメントで今回の件は理解できました! ありがとうございます。 あくまでも基本は「scope_test実行中の名前空間」なのでnonlocalを使わない限り「scope_test実行中の名前空間」が適用されてspamも"test spamが適用されているということですね。
quickquip

2021/06/18 03:41

> あくまでも基本は「scope_test実行中の名前空間」なのでnonlocalを使わない限り「scope_test実行中の名前空間」が適用されてspamも"test spamが適用されているということですね。 はい。 scope_testで実行される文の中でのspamという名前は 1. spam = の代入文がある 2. nonlocal spam も global spam もない の2点によってローカル変数として認識され、『「scope_test実行中の名前空間」のspam』として扱われます。
guest

0

  • def do_localは関数ではないのでしょか?

関数オブジェクトを値に持つ変数です。普通はそういうものを関数と呼んでいます。

まず、関数オブジェクトと関数に束縛されている名前はべつのものであることを理解してください。

def func0():

を行ったときにはdef文は関数オブジェクトを作成し、func0という名前に作成した関数オブジェクトを束縛します。つまりfunc0という変数の値が作成した関数関数オブジェクトになるということです。

ご質問の場合だと、do_localという名前はscope_testの定義内に閉じていますので、その名前でアクセスすることはscope_testの中でしかできません。

名前をglobal宣言しておけば、外でもアクセスすることができるようになります。
以下をご覧ください。

python

1>>> def scope_test(): 2... global do_local 3... def do_local(): 4... spam = "local spam" 5... print(spam) 6... 7>>> scope_test() 8>>> do_local() 9local spam 10

投稿2021/06/17 01:47

ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shingodate1

2021/06/18 02:55

さようでございましたか。 global+関数名とおくことで関数内の関数オブジェクトを関数外でも出力できるということですね。 今回もご指導して頂きありがとうございます。
guest

0

def do_local() は関数定義ですし、関数内での関数定義ですから、このdo_localはscope_test内だけで使える関数です。

スコープの関係を示すための例で、関数はスコープを持っているので、関数を関数の中で定義して入れ子にしています。

投稿2021/06/17 00:43

TakaiY

総合スコア12765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問