Một nguồn khó khăn với câu hỏi này là bạn có một chương trình mang tên bar/bar.py: import barnhập khẩu hoặc bar/__init__.pyhoặc bar/bar.py, tùy thuộc vào nơi nó được thực hiện, mà làm cho nó một chút rườm rà để theo dõi mà alà bar.a.
Đây là cách nó làm việc:
Chìa khóa để hiểu những gì xảy ra là để nhận ra rằng trong bạn __init__.py,
from bar import a
trên thực tế, điều gì đó giống như
a = bar.a
# … where bar = bar/bar.py (as if bar were imported locally from __init__.py)
và xác định một biến mới ( bar/__init__.py:a, nếu bạn muốn). Vì vậy, bạn from bar import aở __init__.pyvới phím tắt tên bar/__init__.py:avới bản gốc bar.py:ađối tượng ( None). Đây là lý do tại sao bạn có thể làm from bar import a as a2trong __init__.py: trong trường hợp này, rõ ràng là bạn có cả hai bar/bar.py:avà một tên biến riêng biệtbar/__init__.py:a2 (trong trường hợp của bạn, tên của hai biến chỉ xảy ra với cả hai a, nhưng chúng vẫn tồn tại trong các không gian tên khác nhau: in __init__.py, chúng bar.avà a).
Bây giờ, khi bạn làm
import bar
print bar.a
bạn đang truy cập biến bar/__init__.py:a(vì import barnhập của bạn bar/__init__.py). Đây là biến bạn sửa đổi (thành 1). Bạn không chạm vào nội dung của biến bar/bar.py:a. Vì vậy, khi bạn sau đó làm
bar.foobar()
bạn gọi bar/bar.py:foobar(), truy cập biến atừ bar/bar.pyđó vẫn là biến None(khi foobar()được định nghĩa, nó liên kết các tên biến một lần và mãi mãi, vì vậy, atrong bar.pylà bar.py:a, không phải bất kỳ abiến nào khác được xác định trong mô-đun khác — vì có thể có nhiều abiến trong tất cả các mô-đun đã nhập ). Do đó Noneđầu ra cuối cùng .
Kết luận: tốt nhất là tránh bất kỳ sự mơ hồ nào trong đó import bar, bằng cách không có bất kỳ bar/bar.pymô-đun nào (vì đã bar.__init__.pytạo thư mục bar/thành một gói nên bạn cũng có thể nhập với import bar).