Jaki jest związek między zakresem a przestrzeniami nazw w Pythonie?


12

W wielu zasobach stwierdziłem, że „zakres” i „przestrzenie nazw” są używane zamiennie, co wydaje się nieco mylące, ponieważ oznaczają różne rzeczy.

  • Zakres określa region kodu, w którym dostępna jest nazwa.
  • Reguła LEGB określa sposób wyszukiwania nazw.
  • Przestrzeń nazw to miejsce, w którym wyszukujesz nazwiska.

Potem czytam:

  • „nazwy są powiązane z przestrzenią nazw zgodnie z miejscem, w którym zostały przypisane ...” (moim zdaniem dotyczy to zakresów w zakresie leksykalnym).
  • „funkcje dodają dodatkową warstwę przestrzeni nazw do twoich programów” [ ref. ] (czy nie dodają dodatkowego zasięgu lokalnego?)
  • „wszystkie nazwy przypisane w definicji funkcji są umieszczane w zasięgu lokalnym (przestrzeń nazw powiązana z wywołaniem funkcji).”
  • „zakres globalny - czyli przestrzeń nazw, w której zmienne utworzone (przypisane) na najwyższym poziomie pliku modułu są aktywne”.

* wszystkie cytaty pochodzą z nauki Pythona 5. edycja ch17

Czy przestrzenie nazw w Pythonie są zaimplementowane w zakresach? Czy to to samo? Czy ktoś może mnie oświecić?


1
Czy możesz podać referencje do cytatów - mógłbym znaleźć jeden, ale nie drugi.
— jonrsharpe

1
Przestrzenie nazw są tylko jednym rodzajem zakresu. Zobacz stackoverflow.com/questions/291978/...
— Robert Harvey

Odpowiedzi:


16

Nazw jest słownikiem, mapowanie nazwy (ciągami znaków) do wartości. Kiedy wykonujesz zadanie, na przykład a = 1, mutujesz przestrzeń nazw. Kiedy tworzysz odwołanie, na przykład print(a)Python przegląda listę przestrzeni nazw, aby spróbować znaleźć taką z nazwą jako kluczem.

A zakres określa, które nazw będą wyglądały i w jakiej kolejności. Zakres każdego odwołania zawsze zaczyna się w lokalnej przestrzeni nazw i przesuwa na zewnątrz, aż osiągnie globalną przestrzeń nazw modułu, zanim przejdzie do builtins(przestrzeni nazw, która odwołuje się do predefiniowanych funkcji i stałych Pythona, takich jak rangei getattr), która jest końcem linii .

Wyobraź sobie, że masz funkcję o nazwie inner, zagnieżdżoną w nazwie funkcji globalnej outeri innerzawiera ona odwołanie do nazwy. Python najpierw szuka w innerprzestrzeni nazw. Jeśli nie ma tam nazwy, Python następnie sprawdza outerprzestrzeń nazw. Jeśli to się nie powiedzie, Python wypróbuje globalprzestrzeń nazw modułu , a następnie builtinprzestrzeń nazw, ostatecznie wyrzucając a, NameErrorjeśli nazwa nie zostanie znaleziona.

Kiedy mówimy, że xznajduje się w przestrzeni nazw funkcji, mamy na myśli, że jest ona zdefiniowana lokalnie w obrębie funkcji. Kiedy mówimy, że xjest w zakresie funkcji, mamy na myśli xto , że znajduje się w przestrzeni nazw funkcji lub w dowolnej zewnętrznej przestrzeni nazw, w której jest zagnieżdżona przestrzeń nazw funkcji.

Za każdym razem, gdy definiujesz funkcję, tworzysz nową przestrzeń nazw i nowy zakres. Przestrzeń nazw to nowy lokalny skrót nazw. Zakres jest implikowanym łańcuchem przestrzeni nazw, który rozpoczyna się w nowej przestrzeni nazw, a następnie przechodzi przez dowolne zewnętrzne przestrzenie nazw (zewnętrzne zakresy), aż do globalnej przestrzeni nazw (zakres globalny) i do wbudowanych.

Terminy mogą być używane prawie zamiennie, ale nie dlatego, że oznaczają to samo; to dlatego, że bardzo się pokrywają w tym, co sugerują.


3
„Pojęć można używać prawie zamiennie, ale to nie dlatego, że oznaczają to samo; to dlatego, że w dużym stopniu pokrywają się w tym, co sugerują”.
— Nikos,

2
Ta odpowiedź jest dobra w duchu, ale w szczegółach błędna. Klasy w Pythonie nie wprowadzają nowej przestrzeni nazw, dlatego atrybuty klasy muszą być kwalifikowane nazwą klasy i dlatego atrybuty instancji muszą być kwalifikowane nazwą instancji. Poziomy przestrzeni nazw w Pythonie od wewnętrznej do zewnętrznej są Lokalne, Załączające, Globalne i Wbudowane. Klasę można zdefiniować na dowolnym z tych poziomów, ale członkowie klasy muszą zawsze mieć kwalifikacje.
— Rob Smallshire

Masz rację. Klasy nie działają tak, jak powiedziałem. Myślałem, że tworzą zakres leksykalny jak funkcję, ale nie robią tego. Zaktualizuj odpowiedź, jeśli masz czas, w przeciwnym razie zrobię to w pewnym momencie. Dzięki.
— Carl Smith

1
+1 Znakomita odpowiedź, tak oszczędnie ujmująca taką subtelność. Uważam to za bardzo pomocne, dziękuję!
— poszukujący

1
„Przestrzeń nazw to skrót nazw, par wartości, bardzo podobny do słownika Pythona” - Jestem prawie pewien, że przestrzenie nazw są przechowywane jako słowniki Pythona. Na przykład możesz edytować globalną przestrzeń nazw, wywołując globals (), co pozwala bezpośrednio modyfikować słownik w celu powiązania obiektów i nazw: na przykład globals () [name] = "object". W przeciwnym razie świetna odpowiedź.
— Evan Rosica,

4

Jest doskonały artykuł na Python nazw tutaj . Aby zacytować odpowiednią część, aby odpowiedzieć na pytanie dotyczące odniesienia między zakresami i przestrzeniami nazw:

Zakres odnosi się do regionu programu, z którego można uzyskać dostęp do przestrzeni nazw bez prefiksu.

Wyobraź sobie na przykład prosty program do walcowania matryc:

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 ma własną przestrzeń nazw , ale nazwy w przestrzeni nazw modułu również są objęte zakresem .


@CarlSmith zauważa, że wczesna dokumentacja Pythona mówi to samo: „Zakres jest regionem tekstowym programu Python, w którym przestrzeń nazw jest bezpośrednio dostępna.” Bezpośrednio dostępne ”oznacza tutaj, że niekwalifikowane odniesienie do nazwy próbuje znaleźć nazwę w przestrzeni nazw. ”
— jonrsharpe

@CarlSmith, oprócz dodatkowego zakresu nielokalnego / obejmującego, czy tak wiele się zmieniło? Myślę, że mówimy to samo - przestrzeń nazw zawiera nazwy i wartości, a zakres informuje, które przestrzenie nazw są dostępne.
— jonrsharpe

Usunąłem moje stare komentarze.
— Carl Smith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.