Hướng dẫn what is circular dependency in python? - phụ thuộc vòng tròn trong python là gì?

Sự phụ thuộc tròn là gì?

Một sự phụ thuộc tròn xảy ra khi hai hoặc nhiều mô -đun phụ thuộc vào nhau. Điều này là do thực tế là mỗi mô -đun được xác định theo định nghĩa khác (xem Hình 1).

Ví dụ:

functionA():
    functionB()

functionB():
    functionA()

Mã trên mô tả một sự phụ thuộc tròn khá rõ ràng. functionA() gọi functionB(), do đó tùy thuộc vào nó và functionB() gọi functionA(). Loại phụ thuộc tròn này có một số vấn đề rõ ràng, chúng tôi sẽ mô tả thêm một chút trong phần tiếp theo.

Hình 1

Các vấn đề với phụ thuộc tròn

Sự phụ thuộc tròn có thể gây ra khá nhiều vấn đề trong mã của bạn. Ví dụ, nó có thể tạo ra khớp nối chặt chẽ giữa các mô -đun và do đó, giảm khả năng tái sử dụng mã. Thực tế này cũng làm cho mã khó khăn hơn để duy trì trong thời gian dài.

Ngoài ra, các phụ thuộc tròn có thể là nguồn gốc của các lỗi tiềm ẩn, chẳng hạn như đệ quy vô hạn, rò rỉ bộ nhớ và hiệu ứng xếp tầng. Nếu bạn không cẩn thận và bạn có một sự phụ thuộc tròn trong mã của mình, có thể rất khó để gỡ lỗi nhiều vấn đề tiềm ẩn mà nó gây ra.

Nhập hình tròn là gì?

Nhập hình tròn là một hình thức phụ thuộc tròn được tạo ra với câu lệnh nhập trong Python.

Ví dụ: hãy phân tích mã sau:

# module1
import module2

def function1():
    module2.function2()

def function3():
    print('Goodbye, World!')
# module2
import module1

def function2():
    print('Hello, World!')
    module1.function3()
# __init__.py

import module1

module1.function1()

Khi Python nhập một mô -đun, nó sẽ kiểm tra sổ đăng ký mô -đun để xem mô -đun đã được nhập chưa. Nếu mô -đun đã được đăng ký, Python sử dụng đối tượng hiện có đó từ bộ đệm. Đăng ký mô -đun là một bảng các mô -đun đã được khởi tạo và lập chỉ mục bằng tên mô -đun. Bảng này có thể được truy cập thông qua

functionB():
    functionA()
2.

Nếu nó không được đăng ký, Python sẽ tìm thấy mô -đun, khởi tạo nó nếu cần thiết và thực thi nó trong không gian tên của mô -đun mới.

Trong ví dụ của chúng tôi, khi Python đạt đến

functionB():
    functionA()
3, nó tải và thực hiện nó. Tuy nhiên, Module2 cũng gọi cho Module1, từ đó xác định
functionB():
    functionA()
4.

Vấn đề xảy ra khi

functionB():
    functionA()
5 cố gắng gọi
functionB():
    functionA()
6 của Module1. Do Module1 được tải trước và lần lượt được tải mô -đun2 trước khi nó có thể đạt đến
functionB():
    functionA()
6, hàm đó chưa được xác định và ném lỗi khi được gọi:

$ python __init__.py
Hello, World!
Traceback (most recent call last):
  File "__init__.py", line 3, in 
    module1.function1()
  File "/Users/scott/projects/sandbox/python/circular-dep-test/module1/__init__.py", line 5, in function1
    module2.function2()
  File "/Users/scott/projects/sandbox/python/circular-dep-test/module2/__init__.py", line 6, in function2
    module1.function3()
AttributeError: 'module' object has no attribute 'function3'

Cách khắc phục sự phụ thuộc tròn

Nói chung, nhập khẩu tròn là kết quả của các thiết kế xấu. Một phân tích sâu hơn của chương trình có thể đã kết luận rằng sự phụ thuộc không thực sự cần thiết hoặc chức năng phụ thuộc có thể được chuyển sang các mô -đun khác nhau không chứa tham chiếu tròn.

Một giải pháp đơn giản là đôi khi cả hai mô -đun chỉ có thể được hợp nhất thành một mô -đun lớn hơn, lớn hơn. Mã kết quả từ ví dụ của chúng tôi ở trên sẽ trông giống như thế này:

# module 1 & 2

def function1():
    function2()

def function2():
    print('Hello, World!')
    function3()

def function3():
    print('Goodbye, World!')

function1()

Tuy nhiên, mô -đun hợp nhất có thể có một số hàm không liên quan (khớp nối chặt) và có thể trở nên rất lớn nếu hai mô -đun đã có nhiều mã trong đó.

Vì vậy, nếu điều đó không hoạt động, một giải pháp khác có thể là trì hoãn việc nhập Module2 để nhập nó chỉ khi cần thiết. Điều này có thể được thực hiện bằng cách đặt nhập Module2 trong định nghĩa của

functionB():
    functionA()
4:

# module 1

def function1():
    import module2
    module2.function2()

def function3():
    print('Goodbye, World!')

Kiểm tra hướng dẫn thực hành của chúng tôi, thực tế để học Git, với các thực hành tốt nhất, các tiêu chuẩn được công nghiệp chấp nhận và bao gồm bảng gian lận. Ngừng các lệnh git googling và thực sự tìm hiểu nó!

Trong trường hợp này, Python sẽ có thể tải tất cả các chức năng trong Module1 và sau đó chỉ tải mô -đun2 khi cần.

Cách tiếp cận này không mâu thuẫn với cú pháp Python, như tài liệu Python nói: "Đó là thông lệ nhưng không bắt buộc phải đặt tất cả các báo cáo nhập ở đầu mô -đun (hoặc tập lệnh, cho vấn đề đó)".

Tài liệu Python cũng nói rằng nên sử dụng

functionB():
    functionA()
9, thay vì các tuyên bố khác, chẳng hạn như
# module1
import module2

def function1():
    module2.function2()

def function3():
    print('Goodbye, World!')
0 hoặc
# module1
import module2

def function1():
    module2.function2()

def function3():
    print('Goodbye, World!')
1.

Bạn cũng có thể thấy nhiều cơ sở mã bằng cách sử dụng nhập khẩu hoãn lại ngay cả khi không có sự phụ thuộc tròn, tăng tốc độ khởi động, vì vậy điều này không được coi là thực hành xấu (mặc dù nó có thể là thiết kế xấu, tùy thuộc vào dự án của bạn) .

Gói lên

Nhập khẩu tròn là một trường hợp cụ thể của các tài liệu tham khảo tròn. Nói chung, chúng có thể được giải quyết với thiết kế mã tốt hơn. Tuy nhiên, đôi khi, thiết kế kết quả có thể chứa một lượng lớn mã hoặc trộn các chức năng không liên quan (khớp nối chặt).

Bạn đã chạy vào nhập khẩu thông tư trong mã của riêng bạn chưa? nếu là vậy, bạn đã sửa nó như thế nào? Hãy cho chúng tôi biết trong các ý kiến!

Có nghĩa là gì bởi sự phụ thuộc tròn?

Trong kỹ thuật phần mềm, sự phụ thuộc tròn là mối quan hệ giữa hai hoặc nhiều mô -đun trực tiếp hoặc gián tiếp phụ thuộc vào nhau để hoạt động đúng. Các mô -đun như vậy còn được gọi là đệ quy lẫn nhau.a relation between two or more modules which either directly or indirectly depend on each other to function properly. Such modules are also known as mutually recursive.

Làm thế nào để bạn giải quyết một sự phụ thuộc tròn trong Python?

Nhập các mô -đun Python là một bài viết tuyệt vời giải thích nhập khẩu tròn trong Python.Cách dễ nhất để khắc phục điều này là di chuyển nhập đường dẫn vào cuối mô -đun nút.Nhân tiện, có một số lý do nào khác ngoài bạn "thích" nó mà bạn muốn một lớp mỗi mô -đun?

Làm thế nào để bạn khắc phục một vấn đề phụ thuộc tròn?

Để giải quyết các phụ thuộc tròn: Sau đó, có ba chiến lược bạn có thể sử dụng: tìm kiếm các đoạn mã nhỏ có thể được chuyển từ dự án này sang dự án khác.Tìm kiếm mã mà cả hai thư viện phụ thuộc và chuyển mã đó vào một thư viện được chia sẻ mới.Kết hợp Projecta và ProjectB vào một thư viện.Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.

Tôi có nên tránh sự phụ thuộc tròn không?

Các tài liệu của NestJS khuyên rằng các phụ thuộc tròn được tránh nếu có thể.Các phụ thuộc tròn tạo ra các khớp nối chặt chẽ giữa các lớp hoặc mô -đun liên quan, điều đó có nghĩa là cả hai lớp hoặc mô -đun phải được biên dịch lại mỗi khi một trong số chúng được thay đổi.circular dependencies be avoided where possible. Circular dependencies create tight couplings between the classes or modules involved, which means both classes or modules have to be recompiled every time either of them is changed.