2013-04-08 55 views
11

Tôi đang học Python và vẫn là người mới bắt đầu, mặc dù tôi đã nghiên cứu nó trong khoảng một năm nay. Tôi đang cố gắng viết một mô-đun các hàm được gọi trong một mô-đun chính. Mỗi hàm trong mô-đun được gọi cần mô-đun toán học để chạy. Tôi tự hỏi nếu có một cách để làm điều này mà không cần nhập khẩu các mô-đun toán học bên trong các mô-đun được gọi là. Dưới đây là những gì tôi có:Python: Không gian tên với nhập khẩu mô-đun

main.py:

from math import * 
import module1 

def wow(): 

    print pi 


wow() 
module1.cool() 

module1.py:

def cool(): 

    print pi 

Khi chạy main.py tôi nhận được:

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 

Những gì tôi đang có một thời gian hiểu biết cứng là lý do tôi gặp lỗi tên khi chạy main.py. Tôi biết rằng biến số pi trở thành toàn cầu đối với mô đun chính khi nhập vì wow có thể truy cập nó. Tôi cũng biết rằng cool trở thành toàn cầu cho mô đun chính khi nhập vì tôi có thể in module1.cool và nhận <function cool at 0x02B11AF0>. Vì vậy, kể từ khi cool nằm trong không gian tên chung của mô-đun chính, không nên chương trình đầu tiên nhìn vào bên trong hàm cool cho biến pi và sau đó khi không tìm thấy nó ở đó, hãy xem bên trong main mô-đun cho biến pitìm thấy nó ở đó?

Cách duy nhất để giải quyết vấn đề này mà tôi biết là nhập mô-đun toán học bên trong module1.py. Tôi không thích ý tưởng đó, mặc dù bởi vì nó làm cho mọi thứ trở nên phức tạp hơn và tôi là một fan hâm mộ của mã đơn giản, đẹp. Tôi cảm thấy như tôi đang nắm chặt không gian tên, nhưng cần giúp đỡ về cái này. Cảm ơn.

Trả lời

16

Như các chương trình traceback, vấn đề không phải là ở main.py, nhưng trong 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 

Nói cách khác, trong module1, không có tên toàn cầu pi, bởi vì bạn chưa nhập nó đó.Khi bạn làm from math import * trong main.py, chỉ cần nhập mọi thứ từ không gian tên của mô-đun math vào không gian tên của mô-đun main, không phải vào mỗi không gian tên của mô-đun.

Tôi nghĩ điều quan trọng bạn đang bỏ lỡ ở đây là mỗi mô-đun có không gian tên "chung" riêng của nó. Điều này có thể hơi khó hiểu lúc đầu, bởi vì trong các ngôn ngữ như C, có một không gian tên chung duy nhất được chia sẻ bởi tất cả các biến và chức năng của extern. Nhưng một khi bạn vượt qua giả định đó, cách Python làm cho cảm giác hoàn hảo.

Vì vậy, nếu bạn muốn sử dụng pi từ module1, bạn phải làm from math import * trong module1.py. (Hoặc bạn có thể tìm cách khác để tiêm nó — ví dụ: module1.py có thể làm from main import * hoặc main.py có thể làm module1.pi = pi, v.v. Hoặc bạn có thể nhồi nhét pi vào mô-đun builtins/__builtin__ ma thuật hoặc sử dụng các thủ thuật khác. giải pháp là để làm import nơi bạn muốn nó nhập khẩu.)


là một mặt lưu ý, bạn thường không muốn làm from foo import * bất cứ nơi nào ngoại trừ người phiên dịch tương tác hay, thỉnh thoảng, kịch bản cấp cao nhất. Có các ngoại lệ (ví dụ: một vài mô-đun được thiết kế rõ ràng để sử dụng theo cách đó), nhưng quy tắc chung là hoặc là import foo hoặc sử dụng một số from foo import bar, baz có giới hạn.

+1

Cảm ơn bạn đã phản hồi. Nếu tôi hiểu bạn một cách chính xác thì, khi tôi gọi "cool" bên trong main.py, trước tiên nó tìm kiếm pi trong chính nó, nhưng không tìm thấy nó, nó sẽ tìm kiếm pi trong module1.py, _not_ main.py, và rõ ràng là không Không tìm thấy nó. Vì vậy, việc tìm kiếm pi trong trường hợp này bị giới hạn trong không gian tên chung của module1 và không thể truy cập vào không gian tên chung của chính. Thê nay đung không? – SpencerAAA

+1

@ SpencerAAA: Đó là một sự đơn giản hóa quá mức, nhưng chỉ một chút, và nó phù hợp với tất cả các bộ phận liên quan. Xem [Đặt tên và ràng buộc] (http://docs.python.org/2/reference/executionmodel.html#naming-and-binding) để biết chi tiết đầy đủ. – abarnert

+1

@ SpencerAAA: Trên thực tế, bạn cần nhiều hơn một chút so với phần đó để có được tất cả các chi tiết. Tóm lại: tại thời điểm định nghĩa 'cool' được đánh giá, Python xác định rằng' pi' không phải là cục bộ (có nghĩa là, tự do trong phạm vi của hàm), và biên dịch hàm thành 'print_item (globals() ('pi')) '. (Nếu bạn hiểu, hoặc sẵn sàng học, CPython bytecode, hãy thử 'import dis' và' dis.dis (cool) 'để xem _exactly_ nó làm gì.) Sau đó, tìm kiếm' globals' là những gì tuân theo các quy tắc cho tra cứu toàn cầu trong Đặt tên và ràng buộc. – abarnert

6

"Rõ ràng là tốt hơn là ngầm" là một quyết định thiết kế được tạo bởi người tạo Python (khởi chạy python và chạy import this).

Do đó, khi bạn chạy module1.cool(), Python sẽ không tìm kiếm số chưa được xác định pi trong mô-đun main.


Bạn sẽ phải nhập mô-đun toán học rõ ràng bất cứ khi nào bạn muốn sử dụng - đó chỉ là cách Python hoạt động.

Ngoài ra, bạn cũng nên tránh nhập khẩu kiểu from X import *, thực tiễn không tốt. Tại đây, bạn có thể làm: from math import pi.

1

Bên trong mô-đun, bạn có thể chỉ cần xác định from math import pi, chỉ nhập pi từ toán học chứ không phải toàn bộ mô-đun toán.

2

Như những người khác đã nói, không thực sự là toàn cầu pi trong số module1 của bạn. Một giải pháp tốt cho bạn là ai, mà chỉ nhập khẩu pi một lần từ mathrõ ràng đảm bảo rằng pi bạn đang nhận được là một trong những từ module1:

main.py:

import module1 

def wow(): 
    print module1.pi 

wow() 
module1.cool() 

module1.py:

from math import pi 

def cool(): 
    print pi