2013-04-08 32 views
11

Uczę się Pythona i jestem jeszcze początkującym, chociaż uczę się go już od około roku. Próbuję napisać moduł funkcji, który jest wywoływany w ramach modułu głównego. Każda z funkcji w wywołanym module wymaga uruchomienia modułu matematycznego. Zastanawiam się, czy istnieje sposób, aby to zrobić bez importowania modułu matematyki wewnątrz modułu nazywanego. Oto co mam:Python: Przestrzenie nazw z importem modułów

main.py:

from math import * 
import module1 

def wow(): 

    print pi 


wow() 
module1.cool() 

module1.py:

def cool(): 

    print pi 

Uruchamiając main.py uzyskać:

3.14159265359 

Traceback (most recent call last): 
    File "Z:\Python\main.py", line 10, in <module> 
    module1.cool() 
    File "Z:\Python\module1.py", line 3, in cool 
    print pi 
NameError: global name 'pi' is not defined 

Co Mam twardy czas zrozumienia dlatego pojawia się błąd nazwy podczas uruchamiania main.py. Wiem, że zmienna pi staje się globalna dla modułu głównego podczas importu, ponieważ wow może uzyskać do niej dostęp. Wiem również, że cool staje się globalne dla modułu głównego podczas importowania, ponieważ mogę wydrukować module1.cool i uzyskać <function cool at 0x02B11AF0>. Ponieważ cool znajduje się w globalnej przestrzeni nazw modułu głównego, nie powinien najpierw zaglądać do funkcji cool dla zmiennej , a następnie, gdy jej tam nie znajdzie, zajrzyj do modułu main dla zmiennej pi i znaleźć tam?

Jedynym sposobem obejścia tego, o którym wiem, jest zaimportowanie modułu matematycznego do wnętrza module1.py. Nie podoba mi się to, choć jest to bardziej skomplikowane i jestem fanem ładnego, prostego kodu. Czuję, że jestem bliski chwytania przestrzeni nazw, ale potrzebuję pomocy w tej sprawie. Dzięki.

Odpowiedz

16

Jak wynika Traceback, problem nie jest w main.py, ale w module1.py:

Traceback (most recent call last): 
    File "Z:\Python\main.py", line 10, in <module> 
    module1.cool() 
    File "Z:\Python\module1.py", line 3, in cool 
    print pi 
NameError: global name 'pi' is not defined 

Innymi słowy, w module1, nie ma globalnego nazwa pi, ponieważ nie zostały przywiezione to tam.Gdy wykonasz from math import * w main.py, to po prostu zaimportujesz wszystko z przestrzeni nazw modułu math do przestrzeni nazw modułu main, a nie do dla każdego obszaru nazw modułu.

Myślę, że kluczową rzeczą, której tu brakuje, jest to, że każdy moduł ma swoją własną "globalną" przestrzeń nazw. Na początku może to być nieco mylące, ponieważ w językach takich jak C istnieje jedna globalna przestrzeń nazw współużytkowana przez wszystkie zmienne i funkcje extern. Ale kiedy już przekroczysz to założenie, sposób w Pythonie ma sens.

Tak więc, jeśli chcesz użyć pi z module1, musisz wykonać from math import * w module1.py. (Albo można znaleźć jakiś inny sposób, aby wstrzyknąć to, na przykład, module1.py mógłby zrobić from main import * lub main.py mógłby zrobić module1.pi = pi itd Albo można dopchać pi do magicznego modułu builtins/__builtin__, lub korzystać z różnych innych sztuczek. Ale oczywiste rozwiązanie to zrobić import gdzie chcesz importowane.)


na marginesie, zwykle nie chcą zrobić from foo import * nigdzie oprócz interaktywnego interpretera lub niekiedy skrypcie najwyższego poziomu. Istnieją wyjątki (np. Kilka modułów jest wyraźnie zaprojektowanych do użycia w ten sposób), ale zasada jest zgodna z import foo lub z ograniczonym from foo import bar, baz.

+1

Dziękuję za odpowiedź. Jeśli rozumiem cię poprawnie wtedy, gdy wywołuję "cool" w main.py, najpierw szuka pi w samym sobie, ale go nie znajduje, następnie szuka pi w module1.py, _not_ main.py i oczywiście doesn nie znajdź tego. Zatem wyszukiwanie pi w tym przypadku jest ograniczone do globalnej przestrzeni nazw modułu1 i nie może uzyskać dostępu do globalnej przestrzeni nazw głównego. Czy to jest poprawne? – SpencerAAA

+1

@SpencerAAA: To niewielkie uproszczenie, ale tylko niewielkie, i jest odpowiednie dla wszystkich istotnych części. Aby uzyskać szczegółowe informacje, patrz [Nazwy i powiązania] (http://docs.python.org/2/reference/executionmodel.html#naming-and- binding). – abarnert

+1

@SpencerAAA: Właściwie potrzebujesz trochę więcej niż ta sekcja, aby uzyskać wszystkie szczegóły. Krótko mówiąc: w czasie oceny definicji "cool" Python określa, że ​​'pi' nie jest lokalny (to znaczy jest wolny w zakresie funkcji) i kompiluje funkcję w coś podobnego do' print_item (globals() ('pi'))) '. (Jeśli rozumiesz lub chcesz się nauczyć kodu bajtowego CPython, wypróbuj 'import dis' i' dis.dis (cool) ', aby zobaczyć _exactly_ co robi.) Następnie, to' globals'-lookup jest zgodne z regułami globalne wyszukiwanie w nazewnictwie i wiązaniu. – abarnert

6

"Jawność jest lepsza niż domniemana" to decyzja projektowa, która została podjęta przez twórców języka Python (uruchomienie python i uruchomienie import this).

Dlatego po uruchomieniu module1.cool(), Python nie będzie szukać nieokreślonego pi w module main.


Będziesz musiał zaimportować moduł matematyczny jawnie, kiedy zechcesz go użyć - tak właśnie działa Python.

Należy również unikać importowania w stylu from X import *, co jest złym rozwiązaniem. Tutaj możesz zrobić: from math import pi.

1

Wewnątrz modułu można po prostu zdefiniować from math import pi, który importowałby tylko pi z matematyki, ale nie z całego modułu matematycznego.

2

Jak powiedzieli inni, w twoim module1 nie ma globalnego pi. Dobrym rozwiązaniem dla ciebie jest to, co tylko importuje pi raz od math i wyraźnie zapewnia, że ​​pi dostajesz to jeden z module1:

main.py:

import module1 

def wow(): 
    print module1.pi 

wow() 
module1.cool() 

module1.py:

from math import pi 

def cool(): 
    print pi