Jestem nowy w Pythonie i jest coś, co przeszkadzało mi od dłuższego czasu. Czytałem w "Learning Python" Marka Lutza, że kiedy używamy Oświadczenia from, aby zaimportować nazwę obecną w module, pierwszy importuje moduł, a następnie przypisuje nową nazwę (tj. Nazwa funkcji , klasa itp. Obecny w importowanym module), a następnie usuwa obiekt modułu za pomocą oświadczenia {x1}}. Jednak co się stanie, jeśli spróbuję zaimportować nazwę za pomocą from, które odnosi się do nazwy w importowanym module, który sam jest nie importowany? Rozważ poniższy przykład, w którym są dwa moduły mod1.py i mod2.py:

#mod1.py
from mod2 import test
test('mod1.py')        

#mod2.py
def countLines(name):
    print len(open(name).readlines())

def countChars(name):
    print len(open(name).read())

def test(name):
    print 'loading...'
    countLines(name)
    countChars(name)
    print '-'*10

Teraz zobacz, co się dzieje, gdy biegam lub importuję mod1:

>>>import mod1

loading...
3
44
----------

Tutaj, kiedy importowałem i uruchomiłem funkcję test, przebiegał z powodzeniem, chociaż nawet nie importuję countChars lub {x2}} i {X2}}} {x3}} from usunęła {{{} X4}} Obiekt modułu.

Zasadniczo musimy wiedzieć, dlaczego ten kod działa, nawet jeśli rozważam problemy, o których wspomniałem, nie powinno.

Edytuj: Dużo dziękuję wszystkim, którzy odpowiedzieli :)

6
IsolatoR 14 sierpień 2012, 22:03

5 odpowiedzi

Każda funkcja ma atrybut __globals__, który posiada odniesienie do środowiska, w którym wyszukuje zmienne globalne i funkcje.

Funkcja test jest następnie połączona z zmiennymi globalnymi mod2. Więc kiedy nazywa countLines tłumacz zawsze znajdzie odpowiednią funkcję, nawet jeśli napisałeś nowy o tej samej nazwie w module importowanie funkcji.

6
JBernardo 14 sierpień 2012, 18:13

Pozostałe odpowiedzi są lepiej przegubione niż ten, ale jeśli uruchamiasz następujące informacje, widać, że countChars i countLines są faktycznie zdefiniowane w test.__globals__:

from pprint import pprint
from mod2 import test

pprint(test.__globals___)
test('mod1')

Widać, że importowanie test przynosi wzdłuż innych globalów zdefiniowanych w mod2, pozwalając uruchomić funkcję bez martwienia konieczności importowania wszystkiego, czego potrzebujesz.

3
RocketDonkey 14 sierpień 2012, 18:12

Każdy moduł ma swój własny zakres. W obrębie mod1 nie można użyć nazw countLines lub countChars (lub {x3}}).

mod2 sama nie ma wpływu na to, w jaki sposób zdarza się, że jest importowany gdzie indziej; Wszystkie nazwiska zdefiniowane w nim są dostępne w module.

Jeśli ta strona internetowa naprawdę mówi, że obiekt modułu zostanie usunięty za pomocą oświadczenia del, jest źle. del Usuwa tylko nazwiska, nie usuwa obiektów.

1
Wooble 14 sierpień 2012, 18:07

Z Przewodnik po przestrzeni nazw Python,

Nawet jeśli moduły mają własne globalne przestrzenie przestrzeni nazw, nie oznacza to, że wszystkie nazwy mogą być używane z dowolnego miejsca w module. Zakres odnosi się do regionu programu, z którego można uzyskać dostęp do przestrzeni nazw bez prefiksu. SCOPES są ważne dla izolacji, które zapewniają w module. W dowolnym momencie istnieje szereg zakresów działań: zakres bieżącej funkcji, w której jesteś, zakres modułu, a następnie zakres budowy Pythona. To zagnieżdżanie zakresów oznacza, że jedna funkcja nie może uzyskać dostępu do nazw wewnątrz innej funkcji.

Przestrzeń nazw są również szukane na stronie nazw. Oznacza to, że jeśli jest pewna nazwa zadeklarowana w globalnej przestrzeni nazw modułu, możesz ponownie wykorzystać nazwę w funkcji, będąc pewnym, że każda inna funkcja otrzyma nazwę globalną. Oczywiście możesz zmusić funkcję, aby użyć nazwy globalnej przed wprowadzeniem nazwy za pomocą słowa kluczowego "Global". Ale jeśli musisz tego użyć, możesz być lepiej używać zajęć i obiektów.

1
Community 20 czerwiec 2020, 09:12

Oświadczenie import ładuje cały moduł w pamięci, dlatego funkcja test() została pomyślnie.

Ale kiedy użyłeś from stwierdzenie, dlatego nie możesz użyć countLines i countChars bezpośrednio, ale test może na pewno je nazywać.

from oświadczenie zasadniczo ładuje cały moduł i ustawia importowaną funkcję, zmienną itp do globalnej przestrzeni nazw.

Np.

>>> from math import sin
>>> sin(90)               #now sin() is a global variable in the module and can be accesed directly
0.89399666360055785
>>> math
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    math
NameError: name 'math' is not defined
>>> vars()  #shows the current namespace, and there's sin() in it
{'__builtins__': <module '__builtin__' (built-in)>, '__file__': '/usr/bin/idle', '__package__': None, '__name__': '__main__', 'main': <function main at 0xb6ac702c>, 'sin': <built-in function sin>, '__doc__': None}

Rozważmy prosty plik, file.py:

def f1():
   print 2+2

def f2():
   f1()

Importuj tylko F2:

>>> from file import f2
>>> f2()
4

Chociaż importowałem tylko f2() nie f1(), ale przejechał z powodzeniem f1(), ponieważ moduł jest ładowany w pamięci, ale możemy tylko uzyskać dostęp do f2(), ale f2() może Uzyskaj dostęp do innych części modułu.

1
Ashwini Chaudhary 14 sierpień 2012, 18:24