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 bar
nhập khẩu hoặc bar/__init__.py
hoặ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à a
là bar.a
.
Dưới đây là cách hoạt động:
Chìa khóa để hiểu biết những gì xảy ra là để nhận ra rằng trong bạn __init__.py
,
from bar import a
có hiệu lực làm điều gì đó như
a = bar.a # … with bar = bar/bar.py (as if bar were imported locally from __init__.py)
và định nghĩa một biến mới (bar/__init__.py:a
, nếu bạn muốn). Do đó, from bar import a
của bạn trong __init__.py
liên kết tên bar/__init__.py:a
với đối tượng bar.py:a
gốc (None
). Đây là lý do bạn có thể làm from bar import a as a2
trong __init__.py
: trong trường hợp này, rõ ràng là bạn có cả hai bar/bar.py:a
và riêng biệt tên biến bar/__init__.py:a2
(trong trường hợp của bạn, tên của hai biến chỉ xảy ra cho cả hai là a
, nhưng chúng vẫn tồn tại ở các không gian tên khác nhau: trong __init__.py
, chúng là bar.a
và 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
(kể từ import bar
nhập khẩu bar/__init__.py
của bạn). Đâ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 số bar/bar.py:a
. Vì vậy, khi bạn sau đó làm
bar.foobar()
bạn gọi bar/bar.py:foobar()
, mà truy cập biến a
từ bar/bar.py
, mà vẫn còn None
(khi foobar()
được định nghĩa, nó liên kết với tên biến một lần và cho tất cả, vì vậy a
trong bar.py
là bar.py:a
, không phải bất kỳ biến số a
được xác định trong một mô-đun khác — vì có thể có nhiều biến số a
trong tất cả các mô-đun đã nhập). Do đó, đầu ra None
cuối cùng.
Thực ra, tôi tìm thấy P Cách nhập '' của ython sạch hơn nhiều so với Java, bởi vì không gian tên/phạm vi sẽ luôn được giữ đúng cách và không bao giờ can thiệp lẫn nhau theo cách bất ngờ. Giống như ở đây: Thay đổi một ràng buộc của một đối tượng thành một tên trong một không gian tên (đọc: giả định một cái gì đó vào thuộc tính toàn cầu của mô-đun) không bao giờ ảnh hưởng đến các không gian tên khác (đọc: tham chiếu được nhập) trong Python. Nhưng làm như vậy trong Java, vv Trong Python bạn chỉ cần hiểu những gì được nhập khẩu, trong khi trong Java, bạn cũng phải hiểu các module khác trong trường hợp, nó làm thay đổi giá trị này sau này. – Tino
Tôi phải không đồng ý khá vất vả. Việc nhập/bao gồm/sử dụng có một lịch sử lâu dài về việc sử dụng biểu mẫu tham chiếu chứ không phải là dạng giá trị trong sự ham muốn về mọi ngôn ngữ khác. –
Chết tiệt, tôi nhấn trở lại ... có một kỳ vọng nhập khẩu theo tham chiếu (theo @OP). Trong thực tế, một lập trình viên Python mới, không có vấn đề làm thế nào có kinh nghiệm, đã được nói với điều này trong "nhìn ra" loại cách. Điều đó sẽ không bao giờ xảy ra: dựa trên cách sử dụng thông thường, Python đã đi sai đường dẫn. Tạo "giá trị nhập" nếu cần, nhưng không được ký hiệu với các giá trị tại thời điểm nhập. –