Nếu bạn thoát khỏi trình thông dịch Python và quay lại nó, các định nghĩa bạn đã thực hiện (hàm và biến) lúc trước sẽ bị mất. Do đó, nếu bạn muốn viết chương trình dài hơn, bạn nên sử dụng trình soạn thảo văn bản để chuẩn bị đầu vào cho trình thông dịch và chạy nó với đầu vào là file đã được tạo. Việc này được gọi là tạo một script. Khi chương trình của bạn còn dài hơn nữa, bạn có thể chia nó thành nhiều file để bảo trì dễ dàng hơn. Bạn cũng có thể sử dụng các hàm hay dùng mà bạn đã viết trong nhiều chương trình khác nhau mà không cần sao chép toàn bộ định nghĩa của nó vào từng chương trình.
Để thực hiện được điều trên, Python cung cấp cách thức để đưa các định nghĩa vào một file và sử dụng chúng trong một file script hoặc trong một phiên tương tác với trình thông dịch. Một file như vậy được gọi là module; các định nghĩa từ một mô-đun có thể được imported vào các mô-đun khác hoặc vào mô-đun main (tập hợp các biến mà bạn có quyền truy cập trong một script được thực thi ở cấp cao nhất - mức ngoài cùng).
Một mô-đun là một file chứa các định nghĩa và câu lệnh Python. Tên file là tên mô-đun có thêm hậu tố .py
. Trong mô-đun, tên của mô-đun (dưới dạng chuỗi) được lưu sẵn vào biến toàn cục tên __name__
. Ví dụ, sử dụng trình soạn thảo văn bản ưa thích của bạn để tạo một file có tên là fibo.py
trong thư mục hiện tại với các nội dung sau:
# Mô-đun số Fibonacci
def fib(n): # viết chuỗi Fibonacci lên đến n
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a + b
print()
def fib2(n): # trả về dãy Fibonacci đến n
result = []
a, b = 0, 1
while b < n:
result.append (b)
a, b = b, a + b
return result
Bây giờ vào trình thông dịch Python và import mô-đun này bằng lệnh sau:
>>> import fibo
Câu lệnh trên không đưa tên của các hàm (fb1, fb2) được định nghĩa trong fibo
trực tiếp vào trong bảng ký hiệu hiện tại; nó chỉ đưa tên mô-đun fibo
vào thôi. Sau đó bằng cách sử dụng tên mô-đun, bạn có thể truy cập đến các hàm bên trong nó như sau:
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo .__ name__
'fibo'
Nếu bạn định sử dụng một hàm thường xuyên, bạn có thể gán nó cho một tên cục bộ như sau:
>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Một mô-đun có thể chứa các câu lệnh thực thi cũng như các định nghĩa hàm. Các câu lệnh này dùng để khởi tạo mô-đun. Chúng chỉ được chạy chỉ trong lần đầu tiên (first) khi tên mô-đun được xuất hiện trong một câu lệnh import. [1] (Chúng cũng được chạy nếu file module được thực thi dưới dạng file script.)
Mỗi mô-đun có bảng kí hiệu (hàm, biến, ..etc - symbol) riêng của nó, được sử dụng làm bảng kí hiệu toàn cục toàn cục cho tất cả các hàm được định nghĩa bên trong mô-đun. Do đó, người viết mô-đun có thể sử dụng các biến toàn cục trong mô-đun mà không phải lo lắng về các xung đột không mong muốn với các biến toàn cục mà người dùng sử dụng mô-đun định nghĩa. Mặt khác, nếu bạn đã biết rõ về module đó, bạn có thể truy cập trực tiếp vào các biến toàn cục của một mô-đun, như cách bạn tham chiếu đến các hàm của nó, bằng dạng tên mô đun. tên biến
(modname.itemname
).
Mô-đun còn có thể import các mô-đun khác. Thói quen mọi người hay dùng nhưng không bắt buộc, đó là đặt tất cả câu lệnh import
ở đầu mô-đun (hoặc script, hoặc tương tự ). Tên các mô-đun đã import được đặt trong bảng ký hiệu toàn cục của mô-đun đang được import vào.
Có một biến thể của câu lệnh import
để nhập tên từ mô-đun trực tiếp vào bảng biểu tượng của mô-đun hiện tại. Ví dụ:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Cách này không đưa tên mô-đun vào bảng kí hiệu cục bộ (trong ví dụ, fibo
không được sẽ không được thêm vào bảng kí hiệu ).
Thậm chí còn có một biến thể để import tất cả các tên mà mô-đun đã định nghĩa nữa:
>>> from fibo import *
>>> fib (500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
Đoạn này sẽ nhập tất cả các định nghĩa trừ các tên bắt đầu bằng dấu gạch dưới (_
). Hầu như, các lập trình viên Python không sử dụng cách này vì nó sẽ đưa một số tên mà người sử dụng mô đun không được hiểu rõ vào trình thông dịch, dẫn đến có nguy cơ một số tên trùng (mà đã có giá trị trước đó) bị ghi đè giá trị hay mất giá trị.
Lưu ý là, nói chung, việc import sử dụng *
từ một mô-đun hoặc gói được không được khuyến khích, vì nó còn làm cho mã nguồn trở nên khó đọc. Tuy nhiên, bạn có thể sử dụng nó để đỡ phải gõ nhiều nhất là khi làm việc ở chế độ tương tác.
Nếu tên mô-đun được theo sau bởi as
, thì tên phía sau [as
](https: // docs. python.org/3/reference/compound_stmts.html#as) được liên kết trực tiếp với mô-đun đã nhập.
>>> import fibo như fib
>>> fib.fib (500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Đoạn trên sẽ import mô-đun như cách mà import fibo
làm ở trên, chỉ có sự khác biệt duy nhất giờ có một cái tên là fib
được định nghĩa thôi. Sau đó ta sẽ sử dụng fib
thay vì fibo
.
Các tương tự cũng có thể sử dụng được khi sử dụng from
:
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Chú thích
Vì lý liên quan đến tính hiệu quả, mỗi mô-đun chỉ được import một lần cho mỗi phiên làm việc với thông dịch. Do đó, nếu bạn thay đổi mô-đun, bạn phải khởi động lại trình thông dịch hoặc, hãy sử dụng [importlib.reload()
](https://docs.python.org/3/ library / importlib.html # importlib.reload) nếu nó là một mô-đun bạn muốn kiểm tra ngay trong lúc tương tác, ví dụ: import importlib; importlib.reload (modulename)
.
Khi bạn chạy một mô-đun Python bằng câu lệnh:
python fibo.py <tham số>
mã trong mô-đun sẽ được thực hiện giống như khi bạn import nó, nhưng chỉ khác là giá trị __name__
sẽ được trình thông dịch tự động gán là "__main __"
. Lợi dụng điều này, bạn có thể thêm đoạn code sau vào mô đun khi viết:
if __name__ == "__main__":
import sys
fib(int(sys.argv [1]))
bằng cách này, bạn có thể làm cho file vừa có thể được sử dụng làm script, cũng vừa là một mô-đun, bởi vì đoạn code đọc giá trị từ dòng lệnh chỉ chạy nếu mô-đun được thực thi dưới dạng file "main" mà thôi:
$ python fibo.py 50
1 1 2 3 5 8 13 21 34
Nếu mô-đun được import, thì code dành cho main
sẽ không chạy:
>>> import fibo
>>>
Cách làm này thường được sử dụng cho việc cung cấp một giao diện người dùng thuận tiện cho người sử dụng mô đun, hoặc cho mục đích kiểm thử (chạy mô-đun như một scrip để thực hiện một loạt test case ).
Khi một mô-đun có tên là spam
được import, đầu tiên trình thông dịch sẽ tìm kiếm trong các mô-đun nó được tích hợp sẵn, xem có tên nào như thế không. Nếu không tìm thấy, nó sẽ tìm kiếm một file có tên spam.py
trong một danh sách các thư mục có trong biến [sys.path
](https://docs.python.org/3/library/sys.html # sys.path). Giá trị biến sys.path
chứa thư mục từ các vị trí sau:
- Thư mục chứa tập script đầu vào (hoặc thư mục hiện tại khi không có file nào được chỉ định ).
PYTHONPATH
(danh sách các tên thư mục, có cùng cùng cú pháp với biến shellPATH
) .- Mặc định được gán lúc cài đặt.
Chú thích
Trên các hệ thống file hỗ trợ liên kết tượng trưng (liên kết mềm, symlinks), thư mục chứa script đầu là giá trị sau khi truy hết. Nói cách khác, thư mục chứa liên kết tượng trưng không được thêm vào đường dẫn tìm kiếm mô-đun.
Sau khi khởi tạo, các chương trình Python sẽ sửa đổi sys.path
. Thư mục chứa file đang chạy được đặt ở đầu đường dẫn tìm kiếm, còn trước cả đường dẫn thư viện chuẩn. Điều này có nghĩa, nếu cùng tên thì, các file trong thư mục đó sẽ được load vào, chứ không phải mô-đun trong thư mục thư viện. Đây sẽ là lỗi trừ khi việc thay thế này trong dự tính của người sử dụng. Xem phần Mô-đun Chuẩn để biết thêm thông tin.
Để tăng tốc độ tải các mô-đun, Python lưu trữ tạm (caches) một bản đã được biên dịch của từng mô-đun trong thư mục __pycache__
dưới tên dạng module.
version
.pyc
, trong đó "version" là định dạng của file được biên dịch; có cả số phiên bản Python nữa. Ví dụ, trong CPython 3.3, phiên bản được biên dịch của spam.py
sẽ được lưu trữ dưới dạng __pycache __/ spam.cpython-33.pyc
. Quy ước đặt tên này cho phép các mô-đun được biên dịch từ các bản phát hành khác và các phiên bản Python khác nhau cùng tồn tại.
Python kiểm tra ngày sửa đổi của mã nguồn, so sánh với phiên bản đã biên dịch để xem bản đã được biên dịch có bị cũ và cần được biên dịch lại hay không. Đây là một quá trình hoàn toàn tự động. Thêm nữa, các mô đun được biên dịch là độc lập với nền tảng, do đó cùng một thư viện có thể được chia sẻ giữa các hệ thống với các kiến trúc khác nhau.
Python không kiểm tra cache trong hai trường hợp sau. Đầu tiên, nó luôn biên dịch lại và không lưu trữ lại kết quả cho mô đun được tải trực tiếp từ dòng lệnh. Thứ hai, nó không kiểm tra cache nếu không có mô đun nguồn. Để để sử dụng các mô đun không mô đun nguồn (chỉ biên dịch ), mô đun được biên dịch phải nằm trong thư mục nguồn và không phải là một mô-đun nguồn.
Một số mẹo dành cho các chuyên gia:
- Bạn có thể sử dụng tham số [
-O
] (https://docs.python.org/3/using/cmdline.html#cmdoption-o) hoặc [-OO
] (https: //docs.python.org/3/using/cmdline.html#cmdoption-oo) trên lệnh Python để giảm kích thước của một mô-đun được biên dịch. Tham số dòng lệnh-O
loại bỏ các câu lệnh kiểm tra điều kiện (assert), tham số dòng lệnh-OO
loại bỏ cả các câu lệnh kiểm tra điều kiện (assert) và các đoạn __doc__. Vì một số chương trình có thể dựa vào những tính năng có sẵn này, bạn chỉ nên sử dụng tùy chọn này nếu bạn biết rõ mình đang làm gì. Mô-đun được "Tối ưu hóa" sẽ có thẻ dạngopt-
và thường nhỏ hơn. Các bản phát hành trong tương lai có thể thay đổi tác động của việc tối ưu hóa. - Chương trình không chạy nhanh hơn khi đọc từ tập tin
.pyc
khi so sánh với khi nó được đọc từ tập tin.py
; điều duy nhất nhanh hơn về các file.pyc
là tốc độ tải chúng lên bộ nhớ. - Các module sử dụng [
compileall
] (https://docs.python.org/3/library/compileall.html#module-compileall) có thể tạo các file .pyc cho tất cả các mô-đun trong một thư mục. - Có thêm chi tiết về quy trình này, bao gồm biểu đồ lưu lượng của các quyết định, trong PEP 3147.
Python đi kèm với một thư viện các mô-đun chuẩn, được mô tả trong một tài liệu riêng biệt, Tham khảo Thư viện Python ("Tham khảo Thư viện" sau đây ). Một số mô-đun được tích hợp vào trình thông dịch; chúng cung cấp quyền truy cập vào các hoạt động không phải là một phần cốt lõi của ngôn ngữ nhưng vẫn được tích hợp sẵn, hoặc để có tác dụng hoặc cung cấp quyền truy cập vào các các phần cơ bản của hệ điều hành như các lời gọi hệ thống chẳng hạn. Tập hợp các mô-đun như vậy là một tùy chọn cấu hình cũng phụ thuộc vào nền tảng bên dưới (mà python chạy). Ví dụ, mô-đun [winreg
] (https://docs.python.org/3/library/winreg.html#module-winreg) chỉ được cung cấp trên các hệ thống Windows. Một mô-đun đáng chú ý nữa: [sys
] (https://docs.python.org/3/library/sys.html#module-sys), được xây dựng trong mọi trình thông dịch Python. Các biến sys.ps1
và sys.ps2
xác định các chuỗi được sử dụng làm lời nhắc chính và phụ khi giao làm việc với trình biên dịch ở chế độ tương tác: >>>
>>> import sys
>>> sys.ps1
'>>>'
>>> sys.ps2
'... '
>>> sys.ps1 = 'C>'
C> in ('Yuck!')
Yuck!
C>
Hai biến này chỉ được xác định nếu trình thông dịch ở chế độ tương tác.
Biến sys.path
là một danh sách các chuỗi xác định đường dẫn tìm kiếm của trình thông dịch cho các mô-đun. Giá trị của nó được khởi tạo từ một đường dẫn mặc định được lấy từ biến môi trường [PYTHONPATH
] (https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH), hoặc từ một mặc định c sẵn nếu [ PYTHONPATH
] (https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPATH) chưa được đặt. Bạn có thể sửa đổi nó bằng cách sử dụng các hoạt động danh sách chuẩn: >>>
>>> import sys
>>> sys.path.append ('/ ufs / guido / lib / python')
6.3. Hàm [dir ()
] (https://docs.python.org/3/library/functions.html#dir) Hàm
Hàm dựng sẵn [dir()
] (https://docs.python.org/3/library/functions.html#dir) được sử dụng để tìm ra các tên (gồm cả hàm, biến toàn cục) mà mô-đun đã định nghĩa. Nó trả về danh sách các chuỗi được sắp xếp: >>>
>>> import fibo, sys
>>> dir (fibo)
['__name__', 'fib', 'fib2']
>>> dir (sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'thực thi', 'thoát', 'cờ', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'nền tảng', 'tiền tố', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
Khi không có đối số, hàm [dir()
] (https://docs.python.org/3/library/functions.html#dir) liệt kê các tên bạn đã định nghĩa đến vị trí hiện tại: >>>
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir ()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
Lưu ý rằng nó liệt kê tất cả các loại tên: tên biến, tên mô-đun, các hàm, v.v.
[dir ()
] (https://docs.python.org/3/library/functions.html#dir) không liệt kê tên của các hàm và biến tích hợp sẵn của python. Nếu bạn muốn một danh sách của chúng, thì có thể tìm thấy trong mô-đun chuẩn builtins
:>>>
>>> nhập nội trang
>>> dir (nội trang)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
'EOFError', 'Dấu ba chấm', 'EnvironmentError', 'Ngoại lệ', 'Sai',
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'tất cả', 'bất kỳ', 'ascii', 'bin', 'bool', 'bytearray', 'byte', 'có thể gọi',
'chr', 'classmethod', 'biên dịch', 'phức tạp', 'bản quyền', 'tín dụng',
'delattr', 'dict', 'dir', 'divmod', 'liệt kê', 'eval', 'exec', 'thoát',
'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
'băm', 'trợ giúp', 'hex', 'id', 'đầu vào', 'int', 'isinstance', 'issubclass',
'lặp lại', 'len', 'giấy phép', 'danh sách', 'người dân địa phương', 'bản đồ', 'tối đa', 'bộ nhớ',
'phút', 'tiếp theo', 'đối tượng', 'oct', 'mở', 'ord', 'pow', 'print', 'property',
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
'được sắp xếp', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
'zip']
Các gói là một cách để tổ chức, cấu trúc không gian tên mô-đun của Python bằng cách sử dụng "tên mô-đun và dấu chấm". Ví dụ, khi nói mô-đun có tên A.B
thì hiểu là một mô-đun con có tên là B
trong một gói có tên A
. Đơn giản là, việc sử dụng các mô-đun theo cách này, sẽ giúp cho tác giả của các mô-đun khác nhau không phải lo lắng về vấn đề tên biến toàn cục có thể trùng nhau, việc sử dụng tên mô-đun với dấu chấm như thế này giúp tác giả của các gói rất nhiều mô-đun như NumPy hoặc Pillow khỏi phải lo lắng về các tên mô-đun bị trùng nhau.
Giả sử bạn muốn thiết kế một tập hợp các mô-đun (được gọi là một "gói") để xử lý một cách thống nhất (cùng giao diện xử lý) các file âm thanh và dữ liệu âm thanh. Có nhiều định dạng file âm thanh khác nhau (thường được nhận dạng bởi phần mở rộng của chúng, ví dụ: .wav
, .aiff
, .au
), vì vậy bạn có thể cần tạo và bảo trì một tập hợp các mô-đun ngày càng tăng khi chuyển đổi để xử lý các định dạng file khác nhau. Cũng có nhiều thao tác khác nhau mà bạn có thể muốn thực hiện trên dữ liệu âm thanh (chẳng hạn như trộn, thêm tiếng vọng, thực hiện chức năng cân bằng, tạo hiệu ứng stereo nhân tạo), rồi bạn sẽ viết một loạt rất nhiều mô-đun để thực hiện các hoạt động này. Đây là một cấu trúc tham khảo cho gói này (được biểu thị bằng hệ thống file phân cấp):
Gói âm thanh / cấp cao nhất
__init__.py Khởi tạo gói âm thanh
định dạng / Gói con để chuyển đổi định dạng file
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
hiệu ứng / Gói con để xử lý hiệu ứng âm thanh
__init__.py
echo.py
surround.py
revers.py
...
bộ lọc / Gói con để xử lý các bộ lọc
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
Khi import gói, Python tìm kiếm thông qua các thư mục trong biến sys.path
để tìm thư mục con của gói.
Các file __init__.py
phải có trong source của gói giúp cho Python nhận ra các thư mục đó là các gói; điều này được thực hiện để ngăn các thư mục có tên phổ biến, chẳng hạn như string
, làm ẩn các mô-đun hợp lệ trước đó khi nó được tìm thấy sau trong các đường dẫn tìm kiếm mô-đun. Trong trường hợp đơn giản nhất, __init__.py
có thể chỉ là một file rỗng, nhưng nó cũng có thể dùng để thực thi mã khởi tạo cho gói hoặc gán lại biến __all__
, được mô tả sau đây.
Người sử dụng gói có thể import các mô-đun riêng lẻ từ gói, như ví dụ sau:
import sound.effects.echo
Đoạn trên đây sẽ nạp mô-đun con sound.effects.echo
, rồi ở đoạn sau đây, sử dụng một hàm của nó. Hàm này phải được tham chiếu bằng tên đầy đủ.
sound.effects.echo.echofilter (đầu vào, đầu ra, độ trễ = 0,7, atten = 4)
Một cách khác để import mô-đun con là:
from sound.effects import echo
Đoạn trên đây cũng tải mô-đun con echo
, và sau đó có thể sử dụng nó mà không có tiền tố gói của nó nữa, vì vậy nó có thể được sử dụng như sau:
echo.echofilter (đầu vào, đầu ra, độ trễ = 0,7, atten = 4)
Tuy nhiên, một biến thể khác là nạp trực tiếp hàm hoặc biến mong muốn:
from sound.effects.echo import echofilter
Cũng giống ở trên, đoạn trên sẽ nạp mô-đun con echo
, nhưng, sau đó có thể sử dụng trực tiếp hàm echofilter()
của nó:
echofilter (đầu vào, đầu ra, độ trễ = 0,7, atten = 4)
Lưu ý là, khi sử dụng cú pháp from gói import ABC
, cái mô-đun được chỉ định ABC ở đây, có thể là một mô-đun con (hoặc gói con) của gói, hoặc một số tên khác được định nghĩa trong gói, như một hàm, lớp hoặc biến. Câu lệnh import
đầu tiên kiểm tra gói nào là ABC trong đó hay không; nếu không thấy, nó giả định ABC là tên một mô-đun và tiếp tục tìm để nạp nó. Nếu không thấy nữa, nó sẽ bắn ra một ngoại lệ [ImportError
] (https://docs.python.org/3/library/exceptions.html#ImportError).
Ngược lại, khi sử dụng cú pháp dạng import ABC.DEF.GHI
, các phần ABC, DEF trừ phần cuối GHI phải là một gói;n phần cuối cùng GHI có thể là một mô-đun hoặc một gói nhưng không thể là một lớp, hàm hoặc biến được.
Bây giờ, điều gì sẽ xảy ra khi người dùng viết from sound.effects import *
? Lý tưởng nhất, chúng ta sẽ hy vọng rằng đoạn này, bằng cách nào đó xem xét hệ thống tập tin từ thư mục của gói, tìm các mô-đun con có mặt trong gói đó, và nạp tất cả chúng vào. Quá trình này có thể mất nhiều thời gian và việc nạp nhiều mô-đun con như thế này có thể gây ra tác dụng phụ từ việc nạp cả những mô-đun không liên quan. Hiệu ứng do các mô-đun không liên quan này đáng lẽ ra chỉ xảy ra khi mô đun đó được nạp một cách rõ ràng.
Giải pháp duy nhất cho tình huống này là tác giả của gói nên đưa ra một cách rõ ràng về gói. Câu lệnh [import
] (https://docs.python.org/3/reference/simple_stmts.html#import) sử dụng quy ước sau đây: nếu file __init__.py
của một gói định nghĩa một biến danh sách có tên __all__
, nó chính là danh sách các tên mô-đun cần được nạp khi trình thông dịch gặp đoạn from package import *
. Điều này tùy thuộc vào tác giả gói có cập nhật danh sách này khi phiên bản mới của gói được phát hành. Tác giả gói cũng có thể quyết định không hỗ trợ nó, nếu họ không thấy sử dụng để nhập \ * từ gói của họ. Ví dụ, file sound / effects / __ init__.py
có thể chứa đoạn mã sau:
__all__ = ["echo", "surround", "reverse"]
Điều này có nghĩa là from sound.effects import *
sẽ nhập ba tên con được đặt tên là sound
package.
Nếu __all__
không được định nghĩa, câu lệnhfrom sound.effects import *
hiện not import tất cả các submodules từ gói sound.effects
vào không gian tên hiện tại; nó chỉ đảm bảo rằng gói sound.effects
đã được nhập \ (có thể chạy bất kỳ mã khởi tạo nào trong __init __. py
) và sau đó import bất kỳ tên nào được định nghĩa trong gói. Điều này bao gồm bất kỳ tên được định nghĩa \ (và submodules được nạp một cách rõ ràng ) bởi __init __. Py
. Nó cũng bao gồm bất kỳ mô-đun con nào của gói được tải một cách rõ ràng bằng các câu lệnh [import
] (https://docs.python.org/3/reference/simple_stmts.html#import) trước đó. Hãy xem xét mã này:
import sound.effects.echo
import sound.effects.surround
từ import sound.effects *
Trong ví dụ này, các mô đun echo
và surround
được import vào không gian tên hiện tại vì chúng được định nghĩa trong gói sound.effects
rồi, vì thế câu lệnh from ... import
được thi hành sẽ đưa nó vào. ( Cách hoạt động tương tự như khi biến __all__
được định nghĩa.)
Mặc dù một số mô-đun nhất định được thiết kế để chỉ xuất các tên theo một số dạng nhất định khi bạn sử dụng import *
, nhưng việc sử dụng cách import này không tốt không tốt trong mã sản phẩm.
Hãy nhớ rằng, không có gì sai khi sử dụng from <Gói> Import <một số module con cụ thể>
! Trong thực tế, đây là cú pháp được khuyên dùng trừ khi mô-đun được import vào để sử dụng có cùng tên với các gói khác nhau.
Khi các gói được cấu trúc gồm nhiều gói con (như với gói sound
trong ví dụ ), bạn có thể sử dụng cú pháp import tuyệt đối để tham chiếu đến các mô-đun con của các gói anh chị em. Ví dụ, nếu module sound.filters.vocoder
cần sử dụng mô-đunecho
trong gói sound.effects
, nó có thể sử dụng fromsound.effects import echo
.
Bạn cũng có thể sử dụng cú pháp import tương đối, với dạng from module import name
của câu lệnh import. Các câu lệnh import này sử dụng các dấu chấm đầu để chỉ ra các gói hiện tại và gói cha mẹ có liên quan. Ví dụ từ gói surround
module, bạn có thể sử dụng:
from . import echo
from .. import format
from .. filters import equalizer
Lưu ý rằng import 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__ "
, các mô-đun được sử dụng làm mô đun chính của ứng dụng Python phải luôn sử dụng import tuyệt đối.
Nhiều gói hỗ trợ một thuộc tính đặc biệt nữa, tên là [__path__
] (https://docs.python.org/3/reference/import.html#__path__). Nó được khởi tạo là một danh sách chứa tên của các thư mục mã mỗi cái file __init __.py
của gói, việc khởi tạo được thực hiện trước khi mã trong các file đó được thi hành. Biến này có thể được sửa đổi; nhưng làm như vậy sẽ ảnh hưởng đến các tìm kiếm module, các gói con chứa trong gói trong tương lai.
Mặc dù tính năng này thường không cần thiết, nhưng nó có thể được sử dụng để mở rộng tập các mô-đun được tìm thấy trong một gói.
Chú thích
| [1] | Trong thực tế, các định nghĩa hàm cũng là 'các câu lệnh' được 'thi hành'; việc thực hiện định nghĩa hàm cấp mô-đun sẽ import tên hàm vào bảng ký hiệu toàn cục của mô-đun. | | --- |