از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
واردات دایره ای پایتون
سرفصلهای مطلب
وابستگی دایره ای چیست؟
یک وابستگی دایره ای زمانی رخ می دهد که دو یا چند ماژول وابسته باشند روی یکدیگر. این به دلیل این واقعیت است که هر ماژول بر اساس دیگری تعریف شده است (شکل 1 را ببینید).
مثلا:
functionA():
functionB()
و
functionB():
functionA()
کد بالا یک وابستگی دایره ای نسبتاً آشکار را نشان می دهد. functionA()
تماس می گیرد functionB()
، بنابراین بسته به روی آن و functionB()
تماس می گیرد functionA()
. این نوع وابستگی دایره ای دارای مشکلات آشکاری است که در قسمت بعدی کمی بیشتر توضیح خواهیم داد.
شکل 1
مشکلات مربوط به وابستگی های دایره ای
وابستگی های دایره ای می توانند مشکلات زیادی در کد شما ایجاد کنند. برای مثال، ممکن است اتصال محکمی بین ماژول ها ایجاد کند و در نتیجه، قابلیت استفاده مجدد کد را کاهش دهد. این واقعیت همچنین حفظ کد را در طولانی مدت دشوارتر می کند.
علاوه بر این، وابستگیهای دایرهای میتوانند منبع شکستهای بالقوه مانند بازگشتهای بینهایت، نشت حافظه و اثرات آبشاری باشند. اگر مراقب نباشید و یک وابستگی دایره ای در کد خود دارید، اشکال زدایی بسیاری از مشکلات احتمالی که ایجاد می کند می تواند بسیار دشوار باشد.
واردات دایره ای چیست؟
وارد کردن دایره ای شکلی از وابستگی دایره ای است که با آن ایجاد می شود import بیانیه در پایتون
به عنوان مثال، بیایید کد زیر را تجزیه و تحلیل کنیم:
import module2
def function1():
module2.function2()
def function3():
print('Goodbye, World!')
import module1
def function2():
print('Hello, World!')
module1.function3()
import module1
module1.function1()
هنگامی که پایتون یک ماژول را وارد می کند، رجیستری ماژول را بررسی می کند تا ببیند آیا ماژول قبلا وارد شده است یا خیر. اگر ماژول قبلا ثبت شده بود، پایتون از آن شی موجود از کش استفاده می کند. رجیستری ماژول جدولی از ماژول هایی است که با نام ماژول مقداردهی اولیه و نمایه شده اند. از طریق این جدول قابل دسترسی است sys.modules
.
اگر ثبت نشده بود، پایتون ماژول را پیدا می کند، در صورت لزوم آن را مقداردهی اولیه می کند و در فضای نام ماژول جدید اجرا می کند.
در مثال ما، زمانی که پایتون می رسد import module2
، آن را بارگذاری و اجرا می کند. با این حال، module2 نیز ماژول 1 را فراخوانی می کند که به نوبه خود تعریف می کند function1()
.
مشکل زمانی رخ می دهد که function2()
سعی می کند module1 را فراخوانی کند function3()
. از آنجایی که module1 ابتدا بارگذاری شد، و به نوبه خود قبل از رسیدن به آن، module2 بارگذاری شد function3()
، آن تابع هنوز تعریف نشده است و هنگام فراخوانی خطا می دهد:
$ python __init__.py
Hello, World!
Traceback (most recent call last):
File "__init__.py", line 3, in <module>
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'
روش رفع وابستگی های دایره ای
به طور کلی واردات دایره ای نتیجه طراحی های بد است. یک تجزیه و تحلیل عمیق تر از برنامه می تواند به این نتیجه برسد که وابستگی در واقع مورد نیاز نیست، یا اینکه عملکرد وابسته را می توان به ماژول های مختلف منتقل کرد که حاوی مرجع دایره ای نیستند.
یک راه حل ساده این است که گاهی اوقات هر دو ماژول را می توان در یک ماژول واحد و بزرگتر ادغام کرد. کد حاصل از مثال بالا چیزی شبیه به این خواهد بود:
def function1():
function2()
def function2():
print('Hello, World!')
function3()
def function3():
print('Goodbye, World!')
function1()
با این حال، ماژول ادغام شده ممکن است عملکردهای نامرتبط داشته باشد (کوپلینگ محکم) و اگر دو ماژول قبلاً کد زیادی در خود داشته باشند، می تواند بسیار بزرگ شود.
بنابراین اگر این کار نمی کند، راه حل دیگری می تواند به تعویق انداختن آن باشد import از module2 به import آن را تنها زمانی که مورد نیاز است. این را می توان با قرار دادن import از module2 در تعریف function1()
:
def function1():
import module2
module2.function2()
def function3():
print('Goodbye, World!')
در این صورت پایتون قادر خواهد بود تمام توابع را در module1 بارگذاری کند و تنها در صورت نیاز ماژول 2 را بارگذاری کند.
این رویکرد با نحو پایتون مغایرتی ندارد مستندات پایتون می گوید: «این مرسوم است اما لازم نیست همه را قرار دهید import عبارات در ابتدای یک ماژول (یا اسکریپت، برای آن موضوع)”.
اسناد پایتون همچنین می گوید که استفاده از آن توصیه می شود import X
، به جای جملات دیگر، مانند from module import *
، یا from module import a,b,c
.
همچنین ممکن است بسیاری از پایههای کد را مشاهده کنید که از واردات معوق استفاده میکنند، حتی اگر وابستگی دایرهای وجود نداشته باشد، که زمان راهاندازی را تسریع میکند، بنابراین این به هیچ وجه عمل بدی تلقی نمیشود (اگرچه ممکن است طراحی بدی باشد، بسته به اینکه روی پروژه شما).
بسته شدن
واردات دایره ای یک مورد خاص از مراجع دایره ای است. به طور کلی، آنها را می توان با طراحی کد بهتر حل کرد. با این حال، گاهی اوقات، طرح حاصل میتواند حاوی مقدار زیادی کد باشد، یا عملکردهای نامرتبط را با هم ترکیب کند (اتصال فشرده).
آیا در کد خود وارد واردات دایره ای شده اید؟ اگر اینجوریه، پس چطوری درستش کردی؟ در نظرات به ما اطلاع دهید!
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-29 14:48:03