Pythonのスコープと名前空間の関係は何ですか?


12

多くのリソースで、「スコープ」「名前空間」が同じ意味で使用されていることがわかりました。

  • スコープは、名前が利用可能なコードの領域を定義します。
  • LEGBルールは、名前の検索方法を定義します。
  • 名前空間は、名前を検索する場所です。

次に読みました:

  • 「名前は、割り当てられた場所に応じて名前空間にバインドされます...」(レキシカルスコープのスコープを扱うと思います)。
  • 「関数はプログラムに余分な名前空間層を追加します」 [ ref。](ローカルスコープを追加しませんか?)
  • 「関数定義内で割り当てられたすべての名前は、ローカルスコープ(関数呼び出しに関連付けられた名前空間)に入れられます。」
  • 「グローバルスコープ-つまり、モジュールファイルのトップレベルで作成された(割り当てられた)変数が存在するネームスペース」

*すべての引用は、Python 5th edition ch17の学習からのものです

Pythonの名前空間はスコープの実装方法ですか?それらは同じものですか?誰でも私を啓発できますか?


1
引用符の参照を提供してもらえますか-片方は見つかりましたが、もう片方は見つかりませんでした。
jonrsharpe

1
名前空間は、スコープの1つのタイプにすぎません。stackoverflow.com/questions/291978/を
ロバートハーベイ

回答:


16

名前空間には、値に名前(ストリング)をマッピングする辞書です。のような割り当てを行うと、a = 1名前空間を変更していることになります。のようprint(a)に参照を作成すると、Pythonは名前空間のリストを調べて、名前がキーになっている名前空間を探します。

スコープの名前空間が中に、どのような順序で検索されます定義します。任意の参照の範囲は常にローカルネームスペースで開始し、それが上に移動する前に、モジュールのグローバルネームスペースに達するまで外側に移動builtins(名前空間その参照Pythonの事前定義された関数と定数、等rangegetattr)行の終わりで、 。

あなたが持っているという名前の関数を想像innerという名前のグローバル関数内でネストをouter、そしてinner名への参照が含まれています。Pythonは最初にinner名前空間を調べます。名前がない場合、Pythonはouter名前空間を調べます。それが失敗した場合、Pythonはモジュールのglobal名前空間を試し、次に名前空間を試し、名前が見つからない場合はbuiltin最終的にaをスローしNameErrorます。

x関数の名前空間にあると言うときは、関数内でローカルに定義されていることを意味します。x関数のスコープ内にあると言うときx、関数の名前空間にあるか、関数の名前空間が内部にネストされている外部の名前空間にあることを意味します。

関数を定義するたびに、新しい名前空間と新しいスコープを作成します。名前空間は、名前の新しいローカルハッシュです。スコープは、新しいネームスペースから始まり、グローバルネームスペース(グローバルスコープ)、ビルトインに至るまで、外部ネームスペース(アウタースコープ)を介して機能するネームスペースの暗黙のチェーンです。

これらの用語はほぼ同じ意味で使用できますが、同じことを意味するためではありません。それは、それらが暗示するものにおいて多くの部分が重複するためです。


3
「これらの用語はほとんど同じ意味で使用できますが、それは同じことを意味するためではなく、暗示するものが多く重複するためです。」
ニコス

2
この答えは精神的に正しいが、詳細は間違っている。Pythonのクラスは新しい名前空間を導入しません。そのため、クラス属性をクラス名で修飾する必要があり、インスタンス属性をインスタンス名で修飾する必要があります。Pythonの内部から外部までの名前空間のレベルは、ローカル、囲い込み、グローバル、組み込みです。クラスはこれらのレベルのいずれかで定義できますが、クラスのメンバーは常に修飾する必要があります。
ロブスモールシャー

あなたが正しい。クラスは、私が言ったように機能しません。関数のようなレキシカルスコープを作成すると思っていましたが、作成していません。時間がある場合は回答を更新してください。それ以外の場合は、いつか更新します。ありがとう。
カールスミス

1
+1すばらしい答え、そのような微妙さを非常に経済的にカプセル化します。これはとても役に立ちました、ありがとう!
シーカー

1
「名前空間は、Python辞書によく似た名前と値のペアのハッシュです」-名前空間 python辞書として保存されていると確信しています。たとえば、globals()を呼び出すことでグローバル名前空間を編集できます。これにより、辞書を直接変更してオブジェクトと名前をバインドできます(例:globals()[name] = "object")。そうでなければ素晴らしい答え。
エヴァンロシカ

4

Python名前空間に関する優れた記事がここにあります。関連する部分を引用して、スコープと名前空間の間の参照に関する質問に答えるには:

スコープとは、接頭辞なしで名前空間にアクセスできるプログラムの領域を指します。

たとえば、単純なダイスロールプログラムを想像してください。

import random  # 'random' is in module namespace

def roll(sides=6):  # 'roll' is in module namespace, 'sides' is in roll's
    return random.randint(1, sides)  # both 'random' and 'sides' are in scope here

# but sides can't be accessed out here 

roll は独自の名前空間を持っていますが、モジュールの名前空間の名前もscopeにあります。


@CarlSmithは、初期のPythonドキュメントは同じことを述べていることに注意してください。「スコープとは、名前空間に直接アクセスできるPythonプログラムのテキスト領域です。名前空間で。」
jonrsharpe

@CarlSmithは、非ローカル/囲みスコープの追加は別として、それは大きく変わりましたか?私たちは同じことを言っていると思います-名前空間には名前と値が含まれており、スコープはどの名前空間にアクセスできるかを示します。
jonrsharpe

古いコメントを削除しました。
カールスミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.