درک فانکشن main در پایتون

امیرحسین بیگدلو 4 ماه قبل

بسیاری از زبان های برنامه نویسی فانکشنی دارند که به طور اتوماتیک زمانی که سیستم عامل یک برنامه را فراخوانی میکند، اجرا میشود. این فانکشن معمولا main نامیده شده و باید دارای شکل خاصی از return و آرگومان ها را باشد. اما در زبان پایتون، مفسر از بالا به پایین کدها را اجرا میکند و فانکشن خاصی ندارد که به طور اتوماتیک اجرا شود.

 

با این وجود، داشتن یک نقطه شروع مشخص برای اجرای یک برنامه برای درک نحوه عملکرد آن برنامه مفید است. برنامه نویسان پایتون چندین قرارداد برای تعریف این نقطه شروع ارائه کرده اند.

 

در این مقاله موارد زیر را یاد میگیرید:

  • متغیر __name__ چیست و پایتون چطور آنرا ایجاد میکند
  • چرا ممکن است بخواهید از فانکشن ()main استفاده کنید
  • چه قراردادهایی برای تعریف main() در پایتون وجود دارد
  • بهترین روش برای استفاده از فانکشن ()main چیست

 

ویدیو پیشنهادی: ویدیو آشنایی با if name == main در پایتون

 

 #  فانکشن‌ main پایتون

در بعضی از کدهای پایتونی ممکن است یک فانکشن و شرط if خاص ببینید که شبیه به این باشد:

def main():
    print("Hello World!")

if __name__ == "__main__":
    main()

 

در این کد یک فانکشن به نام main وجود دارد که جمله Hello World را چاپ میکند. همچنین یک شرط if نیز وجود دارد که بررسی میکند آیا __name__ برابر با __main__ است یا نه. اگر شرط if برابر با True باشد، فانکشن main را اجرا میکند. این کد در پایتون بسیار مرسوم است و زمانی استفاده میشود که بخواهید مشخص کنید که آیا یک ماژول پایتون مستقیما به عنوان اسکریپت اجرا شده یا در جایی دیگر import شده. برای درک این کد باید اول بفهمید که __name__ چکار میکند.

 

مقاله پیشنهادی: آموزش دستور return پایتون

 

 #  حالت‌های اجرای ماژول در پایتون

به طور کلی، مفسر پایتون میتواند یک ماژول را به دو روش اجرا کند:

  1. میتوانید یک ماژول پایتون را مستقیما به عنوان اسکریپت از کامندلاین اجرا کنید
  2. میتوانید یک ماژول را در ماژول دیگری import کرده و از طریق ماژول دیگر آنرا اجرا کنید

 

مهم نیست که به چه روشی ماژول را اجرا کنید، در هر حال پایتون یک متغیر به نام __name__ را برای شما ایجاد خواهد کرد. مقدار __name__ بستگی به این دارد که به چه روشی ماژول را اجرا کنید.

 

برای درک این موضوع، یک فایل پایتونی به نام execution_methods.py ایجاد کرده و کد زیر را در آن قرار میدهیم:

print("This is my file to test Python's execution methods.")
print("The variable __name__ tells me which context this file is running in.")
print("The value of __name__ is:", repr(__name__))

 

در این کد از سه دستور print استفاده میکنیم. دو دستور اول برای معرفی است و دستور سوم مقدار __name__ را چاپ میکند. متد repr مقدار یک آبجکت را برمیگرداند.

 

در این مقاله ما از کلمات فایل، ماژول و اسکریپت استفاده میکنیم. هیچ تفاوتی خاصی بین این سه وجود ندارد. اما یک تفاوت جزئی هست که بد نیست بلد باشید:

  • File: یک فایل پایتونی، فایلی است که پسوند py. داشته و حاوی کدهای پایتونی است.
  • Script: یک اسکریپت، فایلی است که باید برای اتمام کار از طریق کامندلاین اجرا شود.
  • Module: ماژول به فایلی گفته میشود که باید برای اتمام کار در جای دیگری import شود.

 

مقاله پیشنهادی: ماژول‌ها و پکیج‌های پایتون

 

 +  اجرا از طریق کامندلاین

در این روش باید فایل پایتونی را از طریق کامند لاین اجرا کنید. هنگامی که یک اسکریپت را اجرا می کنید، نمی توانید به صورت تعاملی کدی را که مفسر پایتون اجرا می کند را مشخص کنید. حالا باید اسکریپت پایتونی را از طریق کامندلاین اجرا کنید:

$ python3 execution_methods.py
This is my file to test Python's execution methods.
The variable __name__ tells me which context this file is running in.
The value of __name__ is: '__main__'

 

در این مثال، میبینید که __name__ برابر با __main__ است. اگر یک فایل پایتونی را مستقیما اجرا کنید، مقدار __name__ برابر با __main__ خواهد بود.

 

 

 +  اجرا از طریق import کردن در جایی دیگر

روش دوم برای اجرای کدهای پایتون از طریق import است. وقتی در حال توسعه یک ماژول یا اسکریپت هستید، به احتمال زیاد می خواهید از ماژول هایی استفاده کنید که شخص دیگری قبلاً ساخته است، که برای اینکار می توانید از کلمه کلیدی import استفاده کنید.

 

در حین انجام import، پایتون دستوراتی که در ماژول وارد شده وجود دارد را میخواند. برای درک این موضوع حالت interactive پایتون را اجرا کرده و فایل execution_methods.py را import کنید:

>>> import execution_methods
This is my file to test Python's execution methods.
The variable __name__ tells me which context this file is running in.
The value of __name__ is: 'execution_methods'

 

در مثال بالا، مفسر پایتون سه دستور print را اجرا میکند. نتیجه دو دستور print اول، یکسان هستند اما دستور print سوم متفاوت است. زمانی که مفسر پایتون یک ماژول پایتونی را import میکند، مقدار __name__ آنرا برابر با نام آن ماژول قرار میدهد. که در این مثال از آنجایی که نام ماژول execution_methods.py بود، پس مقدار __name__ برابر شد با execution_methods.

 

مقاله پیشنهادی: آموزش دستور import در پایتون

 

 #  بهترین روش‌های استفاده از فانکشن main پایتون

حالا فهمیدید پایتون چطور به روش‌های مختلف ماژول‌ها را اجرا میکند، میتوانیم روی فانکشن main تمرکز کنیم. این روش‌ها توضیح میدهند که ماژول پایتون از چه روشی قرار است اجرا شود.

 

 

 +  بیشتر کدهایتان را در فانکشن یا کلاس بنویسید

به یاد داشته باشید که پایتون تمام کدی را که در ماژول import شده وجود دارد، اجرا میکند. گاهی اوقات کدی که می نویسید عوارض جانبی دارد که می خواهید کاربر آنها را کنترل کند، مثل:

  • اجرای محاسباتی که زمان زیادی می برد
  • نوشتن روی یک فایل
  • چاپ اطلاعاتی که ترمینال کاربر را به هم می ریزد

 

در این موارد میخواهید اجرای کدهای ماژول import شده را به جای مفسر پایتون به کاربر بسپارید. برای همین بهترین روش قرار دادن بخش زیادی از کد در فانکشن‌ها یا کلاس‌ها است. زمانی که مفسر پایتون به کلمات def یا class میرسد، نام آنها را برای استفاده‌های بعدی به خاطر میسپارد اما بدنه آنها را اجرا نمیکند.

 

کد پایین را فایلی به نام best_practices.py ذخیره کنید:

from time import sleep


print("This is my file to demonstrate best practices.")

def process_data(data):
    print("Beginning data processing...")
    modified_data = data + " that has been modified"
    sleep(3)
    print("Data processing finished.")
    return modified_data

 

در این کد شما ابتدا متد sleep را از ماژول time وارد کرده‌اید. متد sleep به تعداد ثانیه‌هایی که به آن ارسال کنید، مفسر پایتون را متوقف خواهد کرد. سپس در ادامه کد دستور print را دارید که هدف این مثال را چاپ میکند. در آخر یک فانکشن به نام process_data داریم که پنج دستور دارد:

  1. دستور print که به کار میگوید پردازش اطلاعات شروع شده
  2. اطلاعات ورودی را تغییر میدهد
  3. دستور sleep سه ثانیه مفسر پایتون را متوقف میکند
  4. دستور print که به کار میگوید پردازش اطلاعات تمام شده
  5. در آخر اطلاعات را return میکند

 

حالا ببینیم که در صورت اجرای کد بالا از طریق کامندلاین چه اتفاقی میفتد.

 

مفسر پایتون دستور import اول فایل و اولین دستور print را اجرا میکند چون خارج از فانکشن هستند و بعد فانکشن process_data را ایجاد شناخته اما اجرا نمیکند. در آخر اسکریپت بدون هیچ کار دیگری خارج خواهد شد چون در ادامه ما فانکشن process_data را صدا نزده‌ایم.

 

کد پایین نتیجه اجرا اسکریپت بالا است:

$ python3 best_practices.py
This is my file to demonstrate best practices.

 

چیزی که در بالا میبینید، نتیجه اولین print است و نه چیز دیگری. دقت کنید که دستور import هیچ خروجی نداشته است. همچنین دستورات print که در داخل فانکشن process_data بودند نیز اجرا نشده و هیچ خروجی نداشته‌اند.

 

حالا فرض کنید که کد بالا را در یک ماژول دیگر import کنیم. در این حالت نیز کد به همان شکل قبل کار خواهد کرد و تفاوتی نخواهد داشت. به محض اینکه مفسر پایتون، فایل بالا را وارد کند، میتوانید از متغیر‌ها،‌ فانکشن‌ها و کلاس‌های آن استفاده کنید. برای درک این موضوع ما از حالت تعاملی پایتون استفاده میکنیم:

>>> import best_practices
This is my file to demonstrate best practices.

 

تنها خروجی که در مثال بالا میبینید، برای اولین دستور print است که خارج از فانکشن بوده. وارد کرده ماژول time و وجود داشتن فانکشن process_data هیچ خروجی ندارد.

 

دوره پیشنهادی: دوره آموزش پایتون (python)

 

 +  از __name__ برای کنترل نحوه اجرای برنامه استفاده کنید

در همان مثال بالا، اگر بخواهید فانکشن process_data فقط در زمانی که ماژول را مستقیما به عنوان اسکریپت اجرا میکنید، اجرا شود میتوانید از ‌__name__ استفاده کنید. در بالا دیدید که اگر یک فایل پایتونی را مستقیما از کامندلاین اجرا کنید، متغیر __name__ مقدار __main__ را میگیرد. پس میتوانید از کد زیر استفاده کنید:

if __name__ == "__main__":
    data = "My data read from the Web"
    print(data)
    modified_data = process_data(data)
    print(modified_data)

 

در این کد شما از یک شرط if استفاده کردید که اگر مقدار __name__ برابر با __main__ شد، کدهای خاصی را اجرا کند. در داخل شرط مشخص کردیم که فانکشن process_data را نیز اجرا کند.

 

حالا بیایید مستقیما فایل بالا را اجرا کنیم:

$ python3 best_practices.py
This is my file to demonstrate best practices.
My data read from the Web
Beginning data processing...
Data processing finished.
My data read from the Web that has been modified

 

میبینید که تمام کدها اجرا میشوند. حتی آنهایی که داخل فانکشن process_data بودند. اما اگر کد بالا را در جایی دیگر import کنید، شرط if برقرار نبوده و کدهای زیر آن اجرا نخواهد شد:

>>> import best_practices
This is my file to demonstrate best practices.

 

در کد بالا فقط دستور print که خارج از فانکشن بوده، اجرا شد.

 

ویدیو پیشنهادی: ویدیو آموزش عملگر walrus در پایتون

 

 +  ساخت فانکشن main برای اجرای کدهایی که میخواهید

حالا میتوانید کدی بنویسید که میتواند به شکل اسکریپت یا import شده، بدون عوارض جانبی اجرا شود. حالا یاد میگیرید چطور کدی بنویسید که کار دیگر برنامه نویسان پایتون را راحت کند.

 

بسیاری از زبان‌های برنامه نویسی مانند C یا java یک فانکشن به نام main دارند که در زمان کامپایل برنامه، به طور اتوماتیک اجرا میشود. به آن فانکشن entry point یا نقطه شروع گفته میشود که مشخص میکند برنامه از کجا قرار است شروع شود.

 

پایتون به طور پیشفرض فانکشنی برای اینکار ندارد. و شما میتوانید نقطه شروع خود را هر فانکشنی قرار دهید. اما پیشنهاد میشود که نام آنرا همان main بگذارید.

 

فایل best_practices.py را تغییر داده و کدهای زیر را در آن قرار دهید:

from time import sleep


print("This is my file to demonstrate best practices.")

def process_data(data):
    print("Beginning data processing...")
    modified_data = data + " that has been modified"
    sleep(3)
    print("Data processing finished.")
    return modified_data


def main():
    data = "My data read from the Web"
    print(data)
    modified_data = process_data(data)
    print(modified_data)


if __name__ == "__main__":
    main()

 

در این مثال تمام کدی را که میخواهیم مفسر پایتون در زمانی اجرای مستقیم ماژول اجرا کند را در فانکشن main قرار داده‌ایم. و در داخل شرط if فانکشن main را صدا زده‌ایم. این روش بهتر از آن است که تمام کد را مستقما در شرط if قرار بدهیم.

 

 

 +  صدازدن فانکشن‌های دیگر از main

یکی دیگر از روش‌هایی که مرسوم هست، صدا زدن فانکشن‌های دیگر از فانکشن main هست. میتوانید کدهای بزرگ را به قطعات کوچک تقسیم کرده و همه را با هم اجرا کنید.

 

ماژول best_practices.py را به شکل زیر تغییر میدهیم:

from time import sleep


print("This is my file to demonstrate best practices.")


def process_data(data):
    print("Beginning data processing...")
    modified_data = data + " that has been modified"
    sleep(3)
    print("Data processing finished.")
    return modified_data

def read_data_from_web():
    print("Reading data from the Web")
    data = "Data from the web"
    return data

def write_data_to_database(data):
    print("Writing data to a database")
    print(data)


def main():
    data = read_data_from_web()
    modified_data = process_data(data)
    write_data_to_database(modified_data)

if __name__ == "__main__":
    main()

 

در قطعه کد بالا چند فانکش کوچک داشته که میتوانند همزمان با هم کار کنند. این باعث خوانایی بیشتر کد شما خواهد شد.

 

 

 

مطالب مشابه



مونگارد