كيفية استخدام عوامل التفريغ (* ، **) في بايثون؟

نشرت: 2021-07-02

Python هي لغة البرمجة الأكثر استخدامًا. ستتعلم اليوم استخدام إحدى ميزاتها الأساسية - ولكن غالبًا ما يتم تجاهلها - وهي تفريغ حزمتها في Python.

ربما تكون قد شاهدت * و ** في تعليمات برمجية أخرى أو حتى أنك استخدمتها دون أن تعرف بالفعل ما هو الغرض منها. سنستعرض مفهوم التفريغ وكيفية استخدامه لكتابة المزيد من التعليمات البرمجية Pythonic.

فيما يلي قائمة بالمفاهيم التي ستجدها مفيدة أثناء قراءة هذا البرنامج التعليمي:

  • قابل للتكرار : أي تسلسل يمكن تكراره بواسطة حلقة for-loop ، مثل المجموعات والقوائم والمجموعات والقواميس
  • قابل للاستدعاء : كائن Python يمكن استدعاؤه باستخدام أقواس مزدوجة () ، على سبيل المثال myfunction ()
  • شل: بيئة تشغيل تفاعلية تتيح لنا تشغيل كود Python. يمكننا تسميتها عن طريق تشغيل "python" في محطة طرفية
  • متغير: اسم رمزي يخزن كائنًا وله موقع ذاكرة محجوز.

لنبدأ بالارتباك الأكثر شيوعًا: العلامات النجمية في بايثون هي أيضًا عوامل حسابية. تُستخدم علامة النجمة (*) للضرب ، بينما تشير اثنتان منها (**) إلى الأس.

يمكننا إثبات ذلك بفتح غلاف بايثون وكتابة:

 >>> 3*3 9 >>> 3**3 27

ملاحظة: يجب أن يكون لديك Python 3 مثبتًا لمتابعة هذا البرنامج التعليمي. إذا لم يكن مثبتًا لديك ، فراجع دليل تثبيت Python الخاص بنا.

كما ترى ، نستخدم علامة النجمة بعد الرقم الأول وقبل الرقم الثاني. عندما ترى هذا ، فهذا يعني أننا نستخدم المعاملات الحسابية.

من ناحية أخرى ، نستخدم العلامات النجمية (* ، **) قبل عنصر تكراري لفك ضغطه - على سبيل المثال:

 >>> *range(1, 6), (1, 2, 3, 4, 5) >>> {**{'vanilla':3, 'chocolate':2}, 'strawberry':2} {'vanilla': 3, 'chocolate': 2, 'strawberry': 2}

لا تقلق إذا لم تحصل عليه ، فهذه مجرد مقدمة لتفريغ محتويات بايثون. لذا انطلق واقرأ البرنامج التعليمي بأكمله!

ما هو التفريغ؟

التفريغ هو عملية إخراج الأشياء - متكررات مثل القوائم ، والقواميس ، والقواميس. فكر في الأمر على أنه فتح صندوق وإخراج عناصر مختلفة مثل الكابلات أو سماعات الرأس أو USB.

صورة مربع تفريغ
يشبه التفريغ في Python تفريغ صندوق في الحياة الواقعية.

دعنا نترجم هذا المثال نفسه إلى رمز لفهم أفضل:

 >>> mybox = ['cables', 'headphones', 'USB'] >>> item1, item2, item3 = mybox

كما ترى ، نقوم بتعيين العناصر الثلاثة الموجودة داخل قائمة mybox إلى ثلاثة متغيرات هي العنصر 1 ، العنصر 2 ، العنصر 2 . هذا النوع من التخصيص المتغير هو المفهوم الأساسي للتفريغ في بايثون.

إذا حاولت الحصول على قيمة كل عنصر ، فستلاحظ أن العنصر 1 ، يشير إلى "الكابلات" ، العنصر 2 ، يشير إلى "سماعات الرأس" وما إلى ذلك.

 >>> item1 'cables' >>> item2 'headphones' >>> item3 'USB'

حتى هنا ، يبدو أن كل شيء على ما يرام مع هذا الرمز ، ولكن ماذا لو أردنا فك قائمة تحتوي على المزيد من العناصر - الاحتفاظ بنفس المقدار من المتغيرات المعينة؟

 >>> newbox = ['cables', 'headphones', 'USB', 'mouse'] >>> item1, item2, item3 = newbox Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: too many values to unpack (expected 3)

من المحتمل أنك توقعت هذا النوع من الخطأ. نحن في الأساس نخصص 4 عناصر قائمة لثلاثة متغيرات ، كيف تستطيع بايثون تعيين القيم الصحيحة؟

لا يحدث ذلك ، وذلك لأننا حصلنا على خطأ في القيمة مع الرسالة "قيم كثيرة جدًا لفك حزمها". يحدث هذا لأننا نضع ثلاثة متغيرات على اليسار ، وأربع قيم (مناظرة لقائمة Newbox) على اليمين.

إذا حاولت القيام بعملية مماثلة ، ولكن مع وجود متغيرات أكثر من القيم لتفكيكها ، فستحصل على ValueError آخر باستثناء ذلك برسالة مختلفة قليلاً:

 >>> lastbox = ['cables', 'headphones'] >>> item1, item2, item3 = lastbox Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: not enough values to unpack (expected 3, got 2)

ملاحظة: لقد عملنا مع القوائم ولكن يمكنك استخدام هذا الشكل من التفريغ مع أي تكرارات (قوائم ، مجموعات ، مجموعات ، قواميس)

فكيف نتغلب على هذا الوضع؟ هل هناك أي طريقة لفك حزم جميع العناصر القابلة للتكرار لمتغيرين دون الحصول على أي أخطاء؟

بالتأكيد هناك ، ويسمى مشغل التفريغ أو مشغل العلامة النجمية (* ، **). دعونا نرى كيفية استخدامه في بايثون.

كيفية فك القوائم باستخدام عامل التشغيل *

تُستخدم علامة النجمة (*) لفك ضغط جميع قيم التكرارات التي لم يتم تعيينها بعد.

لنفترض أنك تريد الحصول على العنصر الأول والأخير من القائمة دون استخدام الفهارس ، فيمكننا فعل ذلك باستخدام عامل تشغيل العلامة النجمية:

 >>> first, *unused, last = [1, 2, 3, 5, 7] >>> first 1 >>> last 7 >>> unused [2, 3, 5]

كما يمكنك أن تدرك ، نحصل على جميع القيم غير المستخدمة من خلال مشغل النجمة. الطريقة المفضلة لتجاهل القيم هي استخدام متغير تسطير أسفل السطر (_) ، والذي يستخدم أحيانًا كـ "متغير وهمي".

 >>> first, *_, last = [1, 2, 3, 5, 7] >>> _ [2, 3, 5]

لا يزال بإمكاننا استخدام هذه الخدعة حتى إذا كانت القائمة تحتوي على عنصرين فقط:

 >>> first, *_, last = [1, 2] >>> first 1 >>> last 2 >>> _ []

في هذه الحالة ، يخزن متغير الشرطة السفلية (المتغير الوهمي) قائمة فارغة حتى يتمكن المتغيران الآخران من حولهما من الوصول إلى القيم المتاحة في القائمة.

استكشاف الأخطاء وإصلاحها الشائعة

يمكننا تفريغ عنصر فريد من نوعه قابل للتكرار. على سبيل المثال ، قد توصلت إلى شيء مثل هذا:

 >>> *string = 'PythonIsTheBest'

ومع ذلك ، فإن الكود أعلاه سيعيد خطأ نحوي :

 >>> *string = 'PythonIsTheBest' File "<stdin>", line 1 SyntaxError: starred assignment target must be in a list or tuple

هذا لأنه وفقًا لمواصفات PEP:

مجموعة (أو قائمة) موجودة على الجانب الأيسر من مهمة بسيطة

إذا أردنا فك حزم جميع قيم متغير متكرر إلى متغير واحد ، فيجب علينا إعداد مجموعة ، ومن ثم فإن إضافة فاصلة بسيطة ستكون كافية:

 >>> *string, = 'PythonIsTheBest' >>> string ['P', 'y', 't', 'h', 'o', 'n', 'I', 's', 'T', 'h', 'e', 'B', 'e', 's', 't']

مثال آخر هو استخدام دالة النطاق ، التي ترجع سلسلة من الأرقام.

 >>> *numbers, = range(5) >>> numbers [0, 1, 2, 3, 4]

الآن بعد أن تعرفت على كيفية فك ضغط القوائم و tuple بعلامة النجمة ، حان الوقت للدخول في تفريغ القواميس.

كيفية فك القواميس باستخدام عامل تشغيل **

بينما يتم استخدام علامة النجمة المفردة لفك ضغط القوائم والبنود ، يتم استخدام علامة النجمة المزدوجة (**) لفك ضغط القواميس.

لسوء الحظ ، لا يمكننا فك ضغط قاموس إلى متغير واحد كما فعلنا مع المجموعات والقوائم. هذا يعني أن ما يلي سيؤدي إلى حدوث خطأ:

 >>> **greetings, = {'hello': 'HELLO', 'bye':'BYE'} ... SyntaxError: invalid syntax

ومع ذلك ، يمكننا استخدام عامل التشغيل ** داخل الاستدعاءات والقواميس الأخرى. على سبيل المثال ، إذا أردنا إنشاء قاموس مدمج ، مصنوع من قواميس أخرى ، فيمكننا استخدام الكود أدناه:

 >>> food = {'fish':3, 'meat':5, 'pasta':9} >>> colors = {'red': 'intensity', 'yellow':'happiness'} >>> merged_dict = {**food, **colors} >>> merged_dict {'fish': 3, 'meat': 5, 'pasta': 9, 'red': 'intensity', 'yellow': 'happiness'}

هذه طريقة قصيرة جدًا لإنشاء قواميس مركبة ، ومع ذلك ، فهذه ليست الطريقة الرئيسية لتفريغ حزم البيانات في بايثون.

دعونا نرى كيف يمكننا استخدام التفريغ باستخدام العناصر القابلة للاستدعاء

التعبئة في الوظائف: args و kwargs

ربما تكون قد رأيت args و kwargs قبل تنفيذها على الفئات أو الوظائف. دعونا نرى لماذا نحتاج إلى استخدامها جنبًا إلى جنب مع العناصر القابلة للاستدعاء.

التعبئة مع عامل التشغيل * (args)

افترض أن لدينا دالة تحسب حاصل ضرب عددين.

 >>> def product(n1, n2): ... return n1 * n2 ... >>> numbers = [12, 1] >>> product(*numbers) 12

كما ترى ، نقوم بتفكيك أرقام القائمة إلى الوظيفة ، لذلك نقوم بالفعل بتشغيل ما يلي:

 >>> product(12, 1) 12

حتى هنا ، كل شيء يعمل بشكل جيد ، ولكن ماذا لو أردنا تمرير قائمة أطول؟ من المؤكد أنها ستثير خطأ لأن الوظيفة تتلقى حججًا أكثر مما تستطيع إدارتها.

 >>> numbers = [12, 1, 3, 4] >>> product(*numbers) ... TypeError: product() takes 2 positional arguments but 4 were given

يمكننا حل كل هذا فقط عن طريق تعبئة القائمة مباشرة على الوظيفة ، مما يؤدي إلى إنشاء تكرارات بداخلها ويسمح لنا بتمرير أي عدد من الوسائط إلى الوظيفة.

 >>> def product(*args): ... result = 1 ... for i in args: ... result *= i ... return result ... >>> product(*numbers) 144

نحن هنا نتعامل مع المعلمة args على أنها متكررة ، حيث نتجول عبر عناصرها ونعيد حاصل ضرب جميع الأرقام. لاحظ كيف يجب أن يكون رقم البداية للنتيجة واحدًا لأننا إذا بدأنا بصفر ، فستعيد الدالة صفرًا دائمًا.

ملاحظة: args هي مجرد اصطلاح ، يمكنك استخدام أي اسم معلمة آخر

يمكننا أيضًا تمرير أرقام عشوائية إلى الوظيفة دون استخدام قائمة ، تمامًا كما هو الحال مع وظيفة الطباعة المضمنة.

 >>> product(5, 5, 5) 125 >>> print(5, 5, 5) 5 5 5

أخيرًا ، دعنا نحصل على نوع كائن من وسائط الدالة.

 >>> def test_type(*args): ... print(type(args)) ... print(args) ... >>> test_type(1, 2, 4, 'a string') <class 'tuple'> (1, 2, 4, 'a string')

كما هو مذكور في الكود أعلاه ، سيكون نوع args دائمًا tuple ، وسيكون محتواه هو جميع الوسائط التي لا تحتوي على كلمات رئيسية والتي تم تمريرها إلى الوظيفة.

التعبئة مع المشغل ** (kwargs)

كما رأينا سابقًا ، يتم استخدام عامل التشغيل ** حصريًا للقواميس. هذا يعني أنه باستخدام هذا المشغل ، يمكننا تمرير أزواج المفتاح والقيمة إلى الوظيفة كمعامل.

لنقم بإنشاء دالة make_person ، والتي تتلقى وسيطة موضعية "name" وكمية غير محددة من الوسائط ذات الكلمات المفتاحية.

 >>> def make_person(name, **kwargs): ... result = name + ': ' ... for key, value in kwargs.items(): ... result += f'{key} = {value}, ' ... return result ... >>> make_person('Melissa', id=12112, location='london', net_worth=12000) 'Melissa: id = 12112, location = london, net_worth = 12000, '

كما ترى ، تحوّل تعليمة ** kwargs جميع الوسائط التي تحتوي على كلمات مفتاحية إلى قاموس ، يمكننا تكرارها داخل الوظيفة.

ملاحظة: kwargs هي مجرد اصطلاح يمكنك تسمية هذه المعلمة بأي شيء تريده

يمكننا التحقق من نوع kwargs بنفس الطريقة التي فعلنا بها مع args :

 >>> def test_kwargs(**kwargs): ... print(type(kwargs)) ... print(kwargs) ... >>> test_kwargs(random=12, parameters=21) <class 'dict'> {'random': 12, 'parameters': 21}

يتحول المتغير الداخلي kwargs دائمًا إلى قاموس يخزن أزواج المفتاح والقيمة التي تم تمريرها إلى الوظيفة.

أخيرًا ، دعنا نستخدم args و kwargs في نفس الوظيفة:

 >>> def my_final_function(*args, **kwargs): ... print('Type args: ', type(args)) ... print('args: ', args) ... print('Type kwargs: ', type(kwargs)) ... print('kwargs: ', kwargs) ... >>> my_final_function('Python', 'The', 'Best', language='Python', users='A lot') Type args: <class 'tuple'> args: ('Python', 'The', 'Best') Type kwargs: <class 'dict'> kwargs: {'language': 'Python', 'users': 'A lot'}

استنتاج

تعد عوامل التفريغ مفيدة حقًا في المهام اليومية ، والآن أنت تعرف كيفية استخدامها في كل من البيانات الفردية ومعلمات الوظيفة.

تعلمت في هذا البرنامج التعليمي:

  • يمكنك استخدام * للمجموعات والقوائم و ** للقواميس
  • يمكنك استخدام عوامل التفريغ في منشئي الوظائف والفئات
  • يتم استخدام args لتمرير المعلمات غير ذات الكلمات الرئيسية إلى الوظائف
  • يتم استخدام kwargs لتمرير معلمات الكلمات الرئيسية إلى الوظائف.