مفهوم args* و kwargs** در پایتون

در زبان های برنامه نویسی، هر تابع می تواند هیچ، یک یا چندین آرگومان ورودی دریافت کند. در صورتی که هیچ یک از این آرگومان ها دارای مقدار پیش فرض نباشند، پس در زمان فراخوانی باید به ازای هر کدام و به ترتیب از چپ به راست، یک مقدار وارد کنیم.فرض کنید می خواهید عملیاتی ریاضی بر روی n عدد انجام دهید. برای حل این مسئله n تعداد آرگومان های تابع است که قاعدتا n>=2 است. اکنون که طرح مسئله را می دانیم، باید متوجه شده باشیم که n در زمان تعریف تابع آشکار نیست و می تواند بر اساس فراخوانی های بعدی، متغیر باشد.کد شماره ۱در کد بالا (۱) تابعی با سه آرگومان نوشته شده است که مقدار جمع سه عدد ارسالی به آن را برگشت می دهد. در زمان فراخوانی سه پارامتر را به آن ارسال کرده ایم. حال فرض کنید اگر به جای سه پارامتر، دو یا چهار پارامتر ارسال کنیم. در این حالت خطایی مانند خروجی زیر (۱) رخ می دهد.خروجی ۱عبارت args*در تعریف آرگومان های یک تابع، زمانی که پیش از نام آرگومان یک * قرار گیرد، آن متغیر به گونه چندین ورودی پی در پی خواهد بود که برابر با یک تاپل (Tuple) از ورودی ها تفسیر می شود. پارامترهای ورودی مانند فهرست 3 ,2 ,1 ترتیب ورودی ها هستند.*args = 1, 2, 3زمانی که می خواهیم که تاپل را تعریف کنیم دو شیوه زیر در پایتون وجود دارد. هر دو کد زیر یک تاپل از اعداد صحیح می سازند.t1 = (1, 2, 3) t2 = 1, 2, 3البته توجه کنید که قطعا آرگومان های ورودی که با args* فرستاده می شوند، لزوما از یک نوع نیستند. در کد زیر من به جای واژه شناخته شده args*، واژه my_args* را به جای فهرست تاپل آرگومان های ورودی تعیین کرده ام.کد شماره ۲در خط دوم کد بالا (۲)، تابع و به کمک تابع درونی ()type نوع my_args* را قاعدتا کلاس تاپل برگشت می دهد. در این مثال ترتیب ورودی ها رشته، اعشاری، صحیح و بولی هستند که شما می توانید تعداد بیشتر یا کمتر و ترتیب نوع های دیگر یا همگی از یک نوع را ارسال کنید.در کد زیر (۳)، تابع بالا بازنویسی شده است، به گونه ای که دو آرگومان arg1 و arg2 احباری هستند ولی my_args* اختیاری است زیرا که آن می تواند تاپلی از هیچ، یک یا چندین ورودی باشد. پس در شکل زیر می بینید که یک بار با ۶ ورودی فراخوانی کرده ام که دو تای اول مربوط به arg1 و arg2 و چهار تای آخر مربوط به my_args* هستند.func('aa', 10.2, 'b', 12, True, 'h') func('aa', 10.2)کد شماره ۳در کد زیر (۴)، تابعی نوشته ایم که دو آروگومان اجباری arg1 و arg2 تعریف شده است. در ادامه یک تاپل به نام parameters با دو مقدار رشته ای و عدد صحیح تعریف شده است که سپس نام متغیر را به صورت parameters* به تابع فرستاده ایم.کد شماره ۴کد بالا نشان می دهد که می توانیم به تعداد، ترتیب و نوع ورودی های یک تابع، یک تاپل بسازیم و سپس با استفاده از عبارت args* که آغاز آن یک * است، نام متغیر تاپل را به تابع بفرستیم. برای نمونه فرض کنید می خواهیم به پایگاه داده وصل شویم که نام تابع اتصال ()db_connect که ورودی های زیر را نیاز دارد.username = 'amirnami' password = '1234' hostname = 'localhost' port = 3306اکنون می توانیم به جای تعریف خط به خط متغیرهای بالا یک تاپل با ترتیب ورودی های تابع بسازیم و سپس آن را به تابع یک جا ارسال کنیم. توجه کنید در زمان تعریف تاپل (در اینجا connection_parameters) نیازی به استفاده از پرانتزها نیست و به عبارتی اگر جلوی نام متغیر و با استفاده از ویرگول و بدون پرانتز، مقدارهایی را به متغیر بدهیم، آن متغیر از نوع تاپل خواهد بود.connection_parameters = 'amirnami', '1234', 'localhost', 3306 db_connect(*connection_parameters)عبارت kwargs**دو عبارت args* و kwargs** دقیقا دو کاربرد یکسان دارند ولی زمانی که بخواهیم ورودی ها را به صورت تاپل ارسال کنیم از args* و زمانی که بخواهیم به صورت دوتایی های Key:Value ارسال کنیم از kwargs** استفاده کنیم.در کد زیر (۵) یک تابع با متغیر user** تعریف شده است، پس این تابع دوتایی های Key=Value را دریافت می کند. درون تابع نخست نوع متغیر user نشان داده می شود که از نوع کلاس دیکشنری است. سپس سه ورودی fname و lname و age با مقدارشان به تابع فرستاده شده اند.کد شماره ۵در کد زیر (۶) آشکارا ورودی را از نوع دیکشنری را به تابع ()func فرستاده ایم. توجه کنید که دو دیکشنری user1 و user2 تعداد دوتایی های یکسان ندارند (کلید from در user2). سپس این دو متغیر را به صورت user1** و user2** به تابع ()func فرستاده ایم، که ورودی user** را دارد.کد شماره ۶در کد زیر که اینجا برداشته شده است، می خواهیم یک URL در SqlAchemy که برابر با همان Connection String در سی شاپ است را توسط کلاس URL بسازیم. برای این کار، دیکشنری از دوتایی های لازم برای اتصال تعریف کرده ایم که تحت نام parameters است. سپس متغیر را به صورت parameters** به متد سازنده کلاس URL فرستاده ایم.from sqlalchemy.engine.url import URL from sqlalchemy.exc import DatabaseError parameters = { 'drivername' : 'mysql+mysqlconnector', 'username': 'root', 'password': '123', 'host': 'localhost', 'port': 3306, 'database' : 'employees' } mysql_url = URL(**parameters) engine2 = create_engine(mysql_url)