Python: Điểm quan trọng của việc sử dụng nhập khẩu nhập là gì?


8

Tôi không rõ lắm về khía cạnh này. Giả sử bạn có một loạt các tệp .py là các mô-đun riêng biệt của riêng họ.

Tại sao mỗi tệp .py cần nhập các tệp khác khi chúng sử dụng lớp đó? Hay họ làm? Bởi vì tôi khá chắc chắn rằng các ngôn ngữ khác (ví dụ Java), không yêu cầu nhập khi tham chiếu đến các lớp / tệp trong cùng thư mục. Tôi có thể sai.

Câu trả lời:


8

Nói một cách đơn giản, đó là cách nó được thiết kế. Bạn đã đề cập đến Java như một ví dụ ngược lại - các nhà thiết kế ngôn ngữ Java muốn làm cho việc tải lớp hơi ẩn, để họ kiểm tra cùng một thư mục trước khi ném ClassNotFound. Ngoài ra, bạn cần phải đủ điều kiện, giống như trong Python.

Như Tom Anderson đã nói, C làm điều tương tự như Python và đó là ngôn ngữ được biên dịch. Có lẽ bản chất được giải thích của ngôn ngữ có liên quan đến quyết định cuối cùng (về hiệu suất, nhân chứng, v.v.), nhưng cuối cùng thì nó thuộc về nhà phát triển.


Tôi không chắc chắn rằng, "đó là cách nó được thiết kế" thực sự là câu trả lời cho câu hỏi này.
Winston Ewert

2
-1: Tôi không biết rõ về Python, nhưng tôi hiểu rằng bạn phải nhập một gói để sử dụng bất cứ thứ gì trong Python. Trong Java, về mặt kỹ thuật, bạn không bao giờ phải sử dụng các báo cáo nhập khẩu; bạn chỉ có thể viết ra tên đầy đủ, đủ điều kiện của các lớp, vv trong các gói khác.
compman

1
Trình độ chuyên môn là giải quyết đường dẫn đến một đối tượng (lớp, chức năng, bất cứ điều gì). Cho dù nó được thực hiện bởi nhập khẩu hoặc vòng loại cú pháp là không liên quan.
Michael K

3

Bởi vì python được diễn giải mọi thứ bạn nhập có sẵn tại dấu nhắc. Java (và C ++) có bước biên dịch và liên kết có thể tìm kiếm và chỉ bao gồm các hàm được sử dụng

Nếu mọi thứ được nhập tự động, sẽ có 1000 hàm và biến và không thể nhập bất cứ thứ gì nếu không va chạm với một.

chỉnh sửa: Ok nó nhiều hơn một chút so với chỉ được biên dịch so với giải thích. Python được dự định là ngôn ngữ "bao gồm pin" - có sẵn các thư viện để làm hầu hết mọi thứ. Vì bạn sẽ chỉ sử dụng một phần nhỏ trong số những người cần phải có cách tổ chức chúng để bạn chỉ bao gồm những người bạn cần.

Việc nhập từ cú pháp rất thông minh vì bạn có thể nhập toàn bộ thư viện và giữ các tên đủ điều kiện giống như Java hoặc bạn có thể nhập các hàm cụ thể (hoặc tất cả các hàm) vào không gian tên cục bộ

>>>import math
>>> math.sin(0)  #no confusion with any other 'sin'

>>> from math import sin  # or import *
>>> sin(0) # makes equations with sin shorter and simpler

Lý do thứ hai là đặc biệt quan trọng trong một ngôn ngữ năng động như python. Vì bạn không phải xác định các biến trước khi sử dụng chúng, môi trường sẽ khó xử lý nếu sinlà hàm toán học hoặc biến của bạn trong trình thông dịch.


Tôi không hiểu ... Bạn có thể giải thích nó cho người mới không? :(
Chuck Testa

@ChuckTesta Để hiểu đầy đủ về sự khác biệt được thảo luận trong câu trả lời này, bạn cần hiểu sự khác biệt giữa các ngôn ngữ được biên dịch và giải thích - bài đăng trên blog này tóm tắt bằng các thuật ngữ khá đơn giản: blog.julipedia.org/2004/07/ Khăn
Bob

8
Sự khác biệt hoàn toàn không có gì để làm với phiên dịch vs biên dịch. Bạn có thể viết một trình biên dịch Python và sẽ phải hoạt động chính xác giống như trình thông dịch Python. Sự khác biệt đơn giản là các nhà thiết kế của Java (nói) đã quyết định thêm tải các lớp ngầm từ các tệp khác và (các) nhà thiết kế của Python thì không. Lưu ý rằng C được biên dịch, nhưng về cơ bản có cùng quy tắc với Python - bạn không thể sử dụng hàm từ một tệp khác trừ khi bạn # bao gồm một tiêu đề cho nó và liên kết đúng thư viện.
Tom Anderson

2
Điểm này là hợp lệ: tải lớp ngầm sẽ có chi phí thời gian chạy lớn bằng ngôn ngữ được dịch
Simon Bergot

1
@Simon, tại sao nó có chi phí thời gian chạy lớn?
Winston Ewert

1

Hãy tưởng tượng bạn có mã này trong python:

foo = MyObject()
fo.bar()

Rõ ràng, chúng ta đã có một lỗi đánh máy và fonên có foo. Ngay bây giờ trăn nói:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'fo' is not defined

Nhưng với lớp tải ngầm, nó có thể nói:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named fo

đó sẽ là khó hiểu. Tệ hơn nữa, nếu bạn viết sai một tên biến chỉ là tên của một mô-đun, bạn sẽ nhận được một lỗi thậm chí còn khó hiểu hơn khi bạn cố gắng xử lý mô-đun đó như thể đó là biến của bạn. Python không thể biết liệu thứ gì đó là tên lớp, đối tượng hay bất cứ thứ gì.

Mặt khác, Java, tôi tin rằng có thể nói từ cú pháp cho dù một định danh nhất định đề cập đến một lớp hay cái gì khác. Do đó, nó không có vấn đề với việc tạo ra một thông báo lỗi thích hợp.

Nhìn chung, nó phù hợp với triết lý Python là rõ ràng hơn là ẩn. Họ nghĩ rằng tốt hơn là nhập một mô-đun thay vì nhập tự động. Vấn đề thông báo lỗi là yếu tố đóng vai trò quyết định.

Một số người đã gợi ý rằng sẽ có một chi phí thời gian chạy lớn để ẩn nhập khẩu. Tôi không nghĩ vậy. Điều gì xảy ra là một cái gì đó như thế này:

  1. Mã op LOAD_GLOBAL được gọi với tên "foo"
  2. từ điển toàn cầu đã kiểm tra "foo"
  3. từ điển nội dung được kiểm tra cho "foo"
  4. Nếu tìm thấy foo, lưu trữ trên toàn cầu và tiếp tục
  5. Nếu không tìm thấy foo, hãy nâng cao NameError

Để hỗ trợ tải mô-đun ngầm, chúng tôi có thể làm:

  1. Mã op LOAD_GLOBAL được gọi với tên "foo"
  2. từ điển toàn cầu đã kiểm tra "foo"
  3. từ điển nội dung được kiểm tra cho "foo"
  4. Nếu thất bại ở trên, hãy thử import foo
  5. Nếu tìm thấy foo, lưu trữ trên toàn cầu và tiếp tục
  6. Nếu không tìm thấy foo, hãy nâng cao NameError

Lần đầu tiên mô-đun được sử dụng, sẽ mất nhiều thời gian hơn vì trước tiên nó phải tìm kiếm thông qua các từ điển khác. Nhưng đó chỉ là lần đầu tiên và không nên có ý nghĩa về toàn bộ thời gian chạy chương trình.

Sẽ có một chi phí đáng kể, trong trường hợp tên biến sai chính tả. Khi chúng xuất hiện, python sẽ lãng phí thời gian đọc đĩa cố gắng tìm mô-đun. Nhưng nếu điều đó xảy ra, chương trình của bạn sắp chết với dù sao đi nữa và hiệu suất không phải là một mối quan tâm lớn.


1

Có một số khác biệt quan trọng giữa Python và Java; trong khi Java có quy tắc "một lớp trên mỗi tệp", Python thì không. Ngoài ra, không phải mọi thứ trong Python đều là một lớp.

Vì vậy, một mô-đun có thể có các lớp, hàm và chỉ các biến cũ đơn giản - thường là tất cả có liên quan theo một cách nào đó (chẳng hạn như các hàm ngẫu nhiên random, các thói quen toán học trong math, các chuỗi liên kết trong string, v.v.).

Nếu bạn muốn truy cập bất kỳ lớp / hàm / biến nào từ một mô-đun cụ thể, trước tiên bạn phải nhập nó.

Tại sao điều này là một điều tốt?

  • Giữ sạch không gian tên mô-đun (không lộn xộn với tên bạn sẽ không bao giờ sử dụng)
  • Dễ dàng theo dõi trở lại mô-đun thích hợp khi có sự cố
  • Cho phép bạn sử dụng tên mà không sợ lỗi vì tên đang được sử dụng hoặc ghi đè tên đã sử dụng (bạn có thể có math.sinvà các sinchức năng của riêng bạn )
  • Giúp làm rõ cấu trúc chương trình.

1

Một trong những khái niệm quan trọng nhất trong Python là về không gian tên (hãy thực hiện import thismột lúc nào đó để tìm hiểu xem những cái khác là gì). Tôi biết rằng không gian tên cũng tồn tại trong các ngôn ngữ khác, nhưng trong Python bạn chỉ có quyền truy cập vào không gian tên hiện tại, đó là những gì được định nghĩa trong mô-đun hiện tại. Để có quyền truy cập vào các mã định danh khác, bạn cần nhập chúng vào không gian tên hiện tại: bằng cách nhập mô-đun chứa của chúng ( import foocú pháp) hoặc chính tên ( from foo import bar).

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.