Thay đổi trong câu lệnh nhập python3


177

Tôi không hiểu những điều sau đây từ pep-0404

Trong Python 3, nhập khẩu tương đối ngầm trong các gói không còn khả dụng - chỉ hỗ trợ nhập tuyệt đối và nhập tương đối rõ ràng. Ngoài ra, nhập sao (ví dụ từ x nhập *) chỉ được phép trong mã cấp mô-đun.

Nhập khẩu tương đối là gì? Ở những nơi khác, sao nhập được phép trong python2? Hãy giải thích với các ví dụ.

Câu trả lời:


277

Nhập tương đối xảy ra bất cứ khi nào bạn đang nhập một gói liên quan đến tập lệnh / gói hiện tại.

Hãy xem xét cây sau đây chẳng hạn:

mypkg
├── base.py
└── derived.py

Bây giờ, derived.pyyêu cầu của bạn một cái gì đó từ base.py. Trong Python 2, bạn có thể làm như thế này (trong derived.py):

from base import BaseThing

Python 3 không còn hỗ trợ điều đó vì nó không rõ ràng cho dù bạn muốn 'tương đối' hay 'tuyệt đối' base. Nói cách khác, nếu có một gói Python có tên baseđược cài đặt trong hệ thống, bạn sẽ nhận được gói sai.

Thay vào đó, nó yêu cầu bạn sử dụng nhập khẩu rõ ràng, chỉ định rõ ràng vị trí của mô-đun trên cơ sở giống nhau. Bạn derived.pysẽ trông như thế nào:

from .base import BaseThing

Hàng đầu .nói 'nhập basetừ thư mục mô-đun'; nói cách khác, .basebản đồ đến ./base.py.

Tương tự, có ..tiền tố đi lên phân cấp thư mục như ../(với ..modánh xạ tới ../mod.py), và sau đó ...tăng hai cấp độ (../../mod.py ) và cứ thế.

Tuy nhiên, xin lưu ý rằng các đường dẫn tương đối được liệt kê ở trên có liên quan đến thư mục chứa mô-đun hiện tại ( derived.py) chứ không phải thư mục làm việc hiện tại.


@BrenBarn đã giải thích trường hợp nhập sao. Để hoàn thiện, tôi sẽ phải nói như vậy;).

Ví dụ, bạn cần sử dụng một vài mathchức năng nhưng bạn chỉ sử dụng chúng trong một chức năng duy nhất. Trong Python 2, bạn được phép bán lười biếng:

def sin_degrees(x):
    from math import *
    return sin(degrees(x))

Lưu ý rằng nó đã kích hoạt cảnh báo trong Python 2:

a.py:1: SyntaxWarning: import * only allowed at module level
  def sin_degrees(x):

Trong mã Python 2 hiện đại, bạn nên và trong Python 3, bạn phải thực hiện:

def sin_degrees(x):
    from math import sin, degrees
    return sin(degrees(x))

hoặc là:

from math import *

def sin_degrees(x):
    return sin(degrees(x))

14

Đối với hàng nhập khẩu tương đối xem tài liệu . Nhập tương đối là khi bạn nhập từ một mô-đun so với vị trí của mô-đun đó, thay vì hoàn toàn từsys.path .

Đối với import *, nhập khẩu sao Python 2 cho phép trong phạm vi chức năng, ví dụ:

>>> def f():
...     from math import *
...     print sqrt

Một cảnh báo được đưa ra cho điều này trong Python 2 (ít nhất là các phiên bản gần đây). Trong Python 3, nó không còn được cho phép nữa và bạn chỉ có thể thực hiện nhập sao ở cấp cao nhất của mô-đun (không phải bên trong các hàm hoặc lớp).


6
Tại sao quyết định đó được đưa ra?
Dor

1
Tôi đoán là ý tưởng đằng sau nó là 'Rõ ràng là tốt hơn ngầm'. từ PEP20 - Zen của Python. Chấm trước khi mô-đun làm cho liên kết tương đối / không liên quan rõ ràng do đó giải quyết xung đột tên có thể. Mặc dù 'Tính dễ đọc.' chịu đựng một chút
Pafnucy

2
Không, trên thực tế, đó là quyết định "ngược lại", "thực tế đánh bại sự thuần khiết". Điều đó là cần thiết để tối ưu hóa truy cập biến cục bộ bên trong các hàm, vì không có "import *", trình biên dịch luôn biết chỉ bằng cách phân tích mã, biến nào là cục bộ và có thể được tra cứu trực tiếp. Trong thực tế, các hàm thậm chí không sử dụng một lệnh cho lưu trữ cục bộ, nhưng một mảng được tối ưu hóa nơi các biến có các chỉ số duy nhất.
Veky

11

Để hỗ trợ cả Python 2 và Python 3, hãy sử dụng nhập tương đối rõ ràng như dưới đây. Chúng có liên quan đến các mô-đun hiện tại. Họ đã được hỗ trợ bắt đầu từ 2.5 .

from .sister import foo
from . import brother
from ..aunt import bar
from .. import uncle

14
nhập .brother cho tôi một lỗi cú pháp không hợp lệ trong Python 3.5. Điều này là bình thường? Tôi có init .py trong thư mục chứa trong đó
Frikster

1
import .brotherlà cú pháp không hợp lệ cho cả python 2 và 3
Rodrigo E. Principe

@ RodrigoE.Principe và dường như là như vậy import ..uncle. Đã sửa. Ồ, những gì tôi đã nghĩ ... có lẽ đã bị phân tâm bởi các hiệp sĩ nói Ni!
Akseli Palén

4

Đã thêm một trường hợp khác vào câu trả lời của Michał Górny:

Lưu ý rằng nhập khẩu tương đối dựa trên tên của mô-đun hiện tại. Vì tên của mô-đun chính luôn là " __main__", nên các mô-đun dự định sử dụng làm mô-đun chính của ứng dụng Python phải luôn sử dụng nhập tuyệt đối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.