Điều gì xảy ra nếu tôi nhập cùng một mô-đun hai lần Python?

Winfried
Thợ rừng

Bài viết. 140

Chủ đề. 60

Đã tham gia. Tháng 8 năm 2018

Danh tiếng. 0

01-04-2021, 02. 13 giờ chiều

Xin chào,

Trong ví dụ này, tôi nhận thấy mô-đun được nhập hai lần.

______0Tôi cho rằng đó là một cách để tiết kiệm một số thao tác nhập bằng cách trỏ trực tiếp vào một số mô-đun phụ. Đúng không?

Cảm ơn bạn.

Hồi đáp

Tìm thấy

Hồi đáp

jefsummers
Da Bishop

Bài viết. 1.265

Chủ đề. 2

Đã tham gia. Tháng 5 năm 2019

Danh tiếng. 85

01-04-2021, 10. 29 giờ tối

Bồn chồn - không.

Xem tài liệu tại tài liệu Python Đặc biệt xem phần 5. 2 trở đi.

Có nhiều lý do để nhập các mô-đun con một cách riêng biệt và trong khi đúng vậy, nó có thể giúp rút ngắn thời gian nhập (và có lẽ là một chút thời gian thực hiện), đặc biệt nếu bạn sử dụng thứ gì đó như nhập matplotlib. pyplot dưới dạng plt

sự khác biệt lớn hơn là việc nhập từng mô-đun con thực thi __init__ của mô-đun con đó. p

Hồi đáp

Tìm thấy

Hồi đáp

deanhystad
Cân như con vịt

Bài viết. 4.330

Chủ đề. 16

Đã tham gia. Tháng 2 năm 2020

Danh tiếng. 254

02-04-2021, 04. 48 giờ sáng

Tôi không biết rằng tôi đồng ý với điều này.

Trích dẫn. một sự khác biệt lớn hơn là việc nhập từng mô hình con thực thi __init__ của mô hình con đó. p
This would be true if each submodule was in a subdirectory of the package, but that doesn't have to be true for submodules.

Take tkinter for example. All the submodules are .py files in the PythonXX\Lib\tkinter folder. import tkinter.ttk imports the ttk module. It would also execute the __init__.py in that folder. However, most programs import tkinter and then tkinter.ttk, so the __init__.py file is already executed by the time we get around to importing ttk. So what you say could be true, but it could also be false.

I was surprised to find out I can do this:
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
In this example the import tkinter.ttk does execute tkinter.__init__.py, and all the tkinter symbols are added to the namespace.

Hồi đáp

Tìm thấy

Hồi đáp

Python được tổ chức thành các mô-đun và gói. Một mô-đun là một tệp Python và một gói là một tập hợp các mô-đun. Xem xét ví dụ sau về nhập mô-đun

import random
random.randint(1,10)

from random import randint
randint(1,10)
8 là một mô-đun tích hợp Python. Trong dòng đầu tiên, nó nhập mô-đun
from random import randint
randint(1,10)
9 và làm cho nó có sẵn để sử dụng, sau đó nó truy cập vào
import pandas
pandas.DataFrame()
0. Nếu bạn mở một IDE và gỡ lỗi quá trình nhập, bạn sẽ thấy mã nằm trong tệp
import pandas
pandas.DataFrame()
1

Bạn cũng có thể nhập

import pandas
pandas.DataFrame()
2 như thế này

from random import randint
randint(1,10)

Hãy xem một ví dụ từ một gói

import pandas
pandas.DataFrame()

Thoạt nhìn, bạn thực sự không thể biết đó là mô-đun hay gói. Nhưng nếu bạn gỡ lỗi quá trình nhập, nó sẽ chuyển hướng bạn đến

import pandas
pandas.DataFrame()
3 thay vì
import pandas
pandas.DataFrame()
4. Một gói chứa các mô-đun con hoặc đệ quy, các gói con và
import pandas
pandas.DataFrame()
5 là điểm vào của gói

Nhưng đó không phải là cách duy nhất, các chức năng như

import pandas
pandas.DataFrame()
6 và
import pandas
pandas.DataFrame()
7 tích hợp cũng có thể được sử dụng

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
5

Bưu kiện. __trong đó__. py

Vậy

import pandas
pandas.DataFrame()
5 là gì?

A chứa tệp

import pandas
pandas.DataFrame()
5. Khi gói được nhập, tệp
import pandas
pandas.DataFrame()
5 này được thực thi hoàn toàn và các đối tượng mà nó xác định được liên kết với các tên trong không gian tên của gói. Tập tin này có thể để trống

Hãy xem một ví dụ. Tôi có một cấu trúc thư mục như thế này.

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
51 là gói của tôi và
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52 là mô hình con

cấu trúc thư mục (Được tạo bởi Xiaoxu Gao)

Bên trong

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 , tôi có một biến
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
54 mà tôi muốn sử dụng trong
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
55. Tôi sẽ tạo một số phiên bản của
import pandas
pandas.DataFrame()
5 và xem nó ảnh hưởng như thế nào đến việc nhập vào
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
55

import random
random.randint(1,10)
6

Trường hợp 1. tập tin

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
58 trống

Vì tệp

import pandas
pandas.DataFrame()
5 trống khi chúng tôi nhập
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
51 , không có mô-đun con nào được nhập, do đó nó không biết sự tồn tại của
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52. Nếu chúng ta nhập
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52 một cách rõ ràng bằng cách sử dụng
import random
random.randint(1,10)
63 thì mọi thứ bên trong
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 sẽ được nhập. Nhưng sau đó, chúng tôi không thực sự nhập gói mà nhập mô-đun. Như bạn có thể tưởng tượng, nếu gói của bạn có nhiều mô-đun con, bạn cần nhập từng mô-đun một cách rõ ràng, điều này có thể khá tẻ nhạt

from random import randint
randint(1,10)
4

Trường hợp2. nhập các mô hình con trong tệp

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
58

Thay vì để trống, chúng tôi nhập mọi thứ từ

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52 vào tệp
import pandas
pandas.DataFrame()
5. Sau đó,
import random
random.randint(1,10)
68 trong tệp
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
55 sẽ nhận ra các biến trong
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 và bạn có thể gọi trực tiếp
from random import randint
randint(1,10)
41 mà không cần biết nó đến từ mô-đun nào

from random import randint
randint(1,10)
2

Bạn có thể đã nhận thấy dấu chấm trước khi

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52. Đó là một lối tắt bảo nó tìm kiếm trong gói hiện tại. Đó là một ví dụ về nhập khẩu tương đối. Nhập tuyệt đối tương đương sẽ đặt tên rõ ràng cho gói hiện tại như
from random import randint
randint(1,10)
43

Có một báo trước mặc dù. Nếu một mô hình con khác trong gói chứa cùng một biến, thì mô hình con được nhập sau sẽ ghi đè lên mô hình con trước đó

Ưu điểm của việc có một

import pandas
pandas.DataFrame()
5 không trống là làm cho tất cả các mô hình con đã có sẵn cho máy khách khi họ nhập gói, vì vậy mã máy khách trông gọn gàng hơn

Python tìm các mô-đun và gói như thế nào?

Hệ thống tìm kiếm các mô-đun và gói trong Python được gọi là Máy nhập khẩu, bao gồm các công cụ tìm, trình tải, bộ đệm và bộ điều phối

Máy móc nhập khẩu (Tạo bởi Xiaoxu Gao)
  1. Mô-đun tìm kiếm trong bộ đệm ẩn
    from random import randint
    randint(1,10)
    45

Mỗi khi bạn nhập một mô-đun, thứ đầu tiên được tìm kiếm là từ điển

from random import randint
randint(1,10)
46. Các khóa là tên mô-đun và các giá trị là chính mô-đun thực tế.
from random import randint
randint(1,10)
46 là một từ điển được lưu trong bộ nhớ cache, nếu mô-đun ở đó thì nó sẽ được trả về ngay lập tức, nếu không, nó sẽ được tìm kiếm trong hệ thống

Quay lại ví dụ trước. Khi chúng tôi nhập

import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
51, hai mục được thêm vào
from random import randint
randint(1,10)
46. Mô-đun cấp cao nhất
import pandas
pandas.DataFrame()
5 và mô-đun con
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53

import pandas
pandas.DataFrame()
3

Nếu chúng ta nhập hai lần, lần nhập thứ hai sẽ đọc từ bộ đệm. Nhưng nếu chúng ta cố tình xóa mục từ từ điển

from random import randint
randint(1,10)
46, thì lần nhập thứ hai sẽ trả về một đối tượng mô-đun mới

import pandas
pandas.DataFrame()
5

2. Thông số mô-đun tìm kiếm

Nếu mô-đun không có trong từ điển

from random import randint
randint(1,10)
46, thì nó cần được tìm kiếm theo danh sách các đối tượng có phương thức
from random import randint
randint(1,10)
24 của chúng để xem liệu mô-đun có thể được nhập hay không

import pandas
pandas.DataFrame()
8

from random import randint
randint(1,10)
25 được sử dụng cho các mô-đun tích hợp.
from random import randint
randint(1,10)
26 được sử dụng để định vị các mô-đun bị đóng băng.
from random import randint
randint(1,10)
27 chịu trách nhiệm tìm các mô-đun nằm ở một trong những đường dẫn này

  • from random import randint
    randint(1,10)
    28
  • from random import randint
    randint(1,10)
    29
  • import pandas
    pandas.DataFrame()
    30
  • import pandas
    pandas.DataFrame()
    31

Hãy xem có gì trong

from random import randint
randint(1,10)
28

from random import randint
randint(1,10)
0

from random import randint
randint(1,10)
27 sẽ sử dụng phương pháp
import pandas
pandas.DataFrame()
34 để tìm kiếm
import pandas
pandas.DataFrame()
35 của mô-đun. Mỗi mô-đun có một đối tượng đặc tả là siêu dữ liệu của mô-đun. Một trong những thuộc tính là
import pandas
pandas.DataFrame()
36.
import pandas
pandas.DataFrame()
36 cho biết máy móc nhập khẩu sử dụng bộ tải nào trong khi tạo mô-đun

from random import randint
randint(1,10)
1

3. Tải mô-đun

Sau khi tìm thấy thông số kỹ thuật của mô-đun, máy nhập sẽ sử dụng thuộc tính trình tải để khởi tạo mô-đun và lưu trữ mô-đun đó trong từ điển

from random import randint
randint(1,10)
46. Bạn có thể đọc phần này để hiểu điều gì xảy ra trong quá trình tải phần nhập

Nhập vòng tròn Python

Cuối cùng, hãy xem xét một vấn đề thú vị về nhập khẩu. Nhập Khẩu Thông Tư. Nhập vòng tròn xảy ra khi hai hoặc nhiều mô-đun phụ thuộc vào nhau. Trong ví dụ này,

import pandas
pandas.DataFrame()
39 phụ thuộc vào
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 và
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 phụ thuộc vào
import pandas
pandas.DataFrame()
39

phụ thuộc mô-đun (Tạo bởi Xiaoxu Gao)
from random import randint
randint(1,10)
2

Python không thể tìm thấy thuộc tính

import pandas
pandas.DataFrame()
53 từ mô-đun
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52. Vậy tại sao điều này xảy ra? . Khi
import pandas
pandas.DataFrame()
55, Python đi qua
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 từng dòng. Điều đầu tiên nó tìm thấy là
import pandas
pandas.DataFrame()
57 , vì vậy nó sẽ nhập
import pandas
pandas.DataFrame()
39. Dòng đầu tiên là nhập
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
52, nhưng vì Python chưa đi qua mọi thứ trong
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53, nên chúng tôi nhận được một đối tượng được khởi tạo một nửa. Khi chúng ta gọi
import pandas
pandas.DataFrame()
81 mà python không nhìn thấy, nó sẽ đưa ra một ngoại lệ AttributeError

Nhập khẩu tròn (Tạo bởi Xiaoxu Gao)

Vậy cách khắc phục nhập vòng như thế nào? . Hầu hết thời gian, sự phụ thuộc không thực sự cần thiết. Một giải pháp đơn giản là hợp nhất cả hai chức năng thành một mô-đun duy nhất

from random import randint
randint(1,10)
3

Đôi khi, mô-đun hợp nhất có thể trở nên rất lớn. Một giải pháp khác là trì hoãn việc nhập

import pandas
pandas.DataFrame()
82 để nhập khi cần. Điều này có thể được thực hiện bằng cách đặt
import pandas
pandas.DataFrame()
57 trong hàm
import pandas
pandas.DataFrame()
84. Trong trường hợp này, Python sẽ tải tất cả các chức năng trong
import tkinter.ttk

x = tkinter.Tk()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
tkinter.Label(x, text="This is a long label").pack()
x.mainloop()
53 và sau đó chỉ tải
import pandas
pandas.DataFrame()
39 khi cần

from random import randint
randint(1,10)
4

Nhiều cơ sở mã sử dụng nhập hoãn lại không nhất thiết phải giải quyết vấn đề phụ thuộc vòng tròn mà để tăng tốc thời gian khởi động. Một ví dụ từ là không viết mã cấp cao nhất không cần thiết để tạo DAG. Điều này là do tác động của tốc độ phân tích cú pháp mã cấp cao nhất đối với cả hiệu suất và khả năng mở rộng của Airflow

from random import randint
randint(1,10)
5

Phần kết luận

Như mọi khi, tôi hy vọng bạn thấy bài viết này hữu ích và đầy cảm hứng. Chúng tôi coi nhiều thứ trong Python là điều hiển nhiên, nhưng thật thú vị khi khám phá cách nó hoạt động bên trong. Hy vọng bạn thích nó, Chúc mừng

Điều gì xảy ra nếu tôi nhập cùng một mô-đun hai lần?

Nếu nhiều mô-đun nhập cùng một mô-đun thì angular chỉ đánh giá mô-đun đó một lần (Khi gặp mô-đun lần đầu tiên). Nó tuân theo điều kiện này ngay cả khi mô-đun xuất hiện ở bất kỳ cấp độ nào trong hệ thống phân cấp NgModules đã nhập. 1.

Chúng tôi có thể nhập một mô-đun hai lần không?

Có, bạn có thể nhập một lớp hai lần trong Java, nó không tạo ra bất kỳ sự cố nào, nhưng bất kể số lần bạn nhập, JVM chỉ tải lớp một lần

Python có nhập mô-đun hai lần không?

Không. Đây thực sự là tiêu chuẩn trong Python . Trên thực tế, Python chỉ tải mô-đun khi nó được nhập trong tệp đầu tiên và tất cả các tệp tiếp theo chỉ cần đặt tên để chỉ mô-đun đã được tải.

Python xử lý các lần nhập trùng lặp như thế nào?

Có, bạn có thể nhập mô-đun bao nhiêu lần tùy thích trong một chương trình Python, bất kể đó là mô-đun nào. Mỗi lần nhập tiếp theo sau lần đầu tiên truy cập vào mô-đun đã lưu trong bộ nhớ đệm thay vì đánh giá lại mô-đun đó .