في هذا النص، يتم استخدام مصطلحات Python وCPython، وهو التطبيق المرجعي للغة، بالتبادل. تتناول هذه المقالة CPython على وجه التحديد ولا تتعلق بأي تطبيق آخر لـ Python.
بايثون هي لغة جميلة تسمح للمبرمج بالتعبير عن أفكاره بعبارات بسيطة مع ترك تعقيد التنفيذ الفعلي وراء الكواليس.
أحد الأشياء التي يتم تجريدها هو الفرز.
يمكنك بسهولة العثور على إجابة السؤال "كيف يتم تنفيذ الفرز في بايثون؟" والذي يجيب دائمًا على سؤال آخر: "ما هي خوارزمية الفرز التي تستخدمها بايثون؟".
ومع ذلك، غالبًا ما يترك هذا بعض تفاصيل التنفيذ المثيرة للاهتمام.
هناك تفاصيل تنفيذ واحدة أعتقد أنها لم تتم مناقشتها بشكل كافٍ، على الرغم من أنها تم تقديمها منذ أكثر من سبع سنوات في بايثون 3.7:
تم تحسينsorted() وlist.sort() للحالات الشائعة لتكون أسرع بنسبة تصل إلى 40-75%. (ساهم بها إليوت جوروكوفسكي في bpo-28685.)
ولكن قبل أن نبدأ...
عندما تحتاج إلى فرز قائمة في بايثون، لديك خياران:
إذا كنت بحاجة إلى فرز أي عنصر قابل للتكرار مضمن آخر، فيمكنك فقط استخدام التصنيف بغض النظر عن نوع العنصر القابل للتكرار أو المولد الذي تم تمريره كمعلمة.
يُرجع الترتيب دائمًا قائمة لأنه يستخدم list.sort داخليًا.
إليك معادل تقريبي لتطبيق CPython المصنف C الذي تمت إعادة كتابته بلغة بايثون خالصة:
def sorted(iterable: Iterable[Any], key=None, reverse=False): new_list = list(iterable) new_list.sort(key=key, reverse=reverse) return new_list
نعم، الأمر بهذه البساطة.
كما تقول الوثائق الداخلية للفرز في Python:
من الممكن أحيانًا استبدال مقارنات أسرع خاصة بالنوع بـ PyObject_RichCompareBool الأبطأ والعامة
وباختصار يمكن وصف هذا التحسين على النحو التالي:
عندما تكون القائمة متجانسة، تستخدم بايثون وظيفة المقارنة الخاصة بالنوع
القائمة المتجانسة هي القائمة التي تحتوي على عناصر من نوع واحد فقط.
على سبيل المثال:
homogeneous = [1, 2, 3, 4]
من ناحية أخرى، هذه ليست قائمة متجانسة:
heterogeneous = [1, "2", (3, ), {'4': 4}]
ومن المثير للاهتمام أن البرنامج التعليمي الرسمي لبايثون ينص على ما يلي:
القوائم قابلة للتغيير، وعناصرها عادة ما تكون متجانسة ويمكن الوصول إليها عن طريق التكرار على القائمة
ينص هذا البرنامج التعليمي نفسه على:
الصفوف غير قابلة للتغيير، وتحتوي عادةً على تسلسل غير متجانس من العناصر
لذا، إذا تساءلت يومًا متى تستخدم صفًا أو قائمة، فإليك القاعدة الأساسية:
إذا كانت العناصر من نفس النوع، استخدم قائمة، وإلا استخدم صفًا
تنفذ بايثون كائن حاوية مصفوفة متجانسة للقيم الرقمية.
ومع ذلك، اعتبارًا من الإصدار python 3.12، لا تقوم المصفوفات بتنفيذ طريقة الفرز الخاصة بها.
الطريقة الوحيدة لفرزها هي استخدام الترتيب، الذي ينشئ قائمة من المصفوفة داخليًا، ويمسح أي معلومات متعلقة بالنوع في العملية.
المقارنات في بايثون مكلفة، لأن بايثون تجري فحوصات مختلفة قبل إجراء أي مقارنة فعلية.
إليك شرح مبسط لما يحدث تحت الغطاء عند مقارنة قيمتين في بايثون:
علاوة على ذلك، تقوم وظائف المقارنة الخاصة بكل نوع بتنفيذ فحوصات إضافية.
على سبيل المثال، عند مقارنة السلاسل، ستتحقق بايثون مما إذا كانت أحرف السلسلة تشغل أكثر من بايت واحد من الذاكرة، وستقوم المقارنة العائمة بمقارنة زوج من float وfloat وint بشكل مختلف.
يمكن العثور على شرح ومخطط أكثر تفصيلاً هنا: إضافة تحسينات فرز البيانات المدركة إلى CPython
قبل تقديم هذا التحسين، كان على بايثون تنفيذ كل هذه الاختبارات المتنوعة الخاصة بالنوع وغير الخاصة بالنوع في كل مرة تتم فيها مقارنة قيمتين أثناء الفرز.
لا توجد طريقة سحرية لمعرفة ما إذا كانت جميع عناصر القائمة من نفس النوع بخلاف التكرار على القائمة والتحقق من كل عنصر.
يقوم بايثون بذلك تقريبًا - التحقق من أنواع مفاتيح الفرز التي تم إنشاؤها بواسطة وظيفة المفتاح التي تم تمريرها إلى list.sort أو فرزها كمعلمة
إذا تم توفير وظيفة رئيسية، فإن بايثون تستخدمها لإنشاء قائمة من المفاتيح، وإلا فإنها تستخدم قيم القائمة الخاصة كمفاتيح فرز.
بطريقة مبسطة، يمكن التعبير عن بناء المفاتيح على شكل كود بايثون التالي.
if key is None: keys = list_items else: keys = [key(list_item) for list_item in list_item]
لاحظ أن المفاتيح المستخدمة داخليًا في CPython هي مصفوفة C من مراجع كائنات CPython، وليست قائمة Python
بمجرد إنشاء المفاتيح، تقوم بايثون بالتحقق من أنواعها.
عند التحقق من أنواع المفاتيح، تحاول خوارزمية الفرز في بايثون تحديد ما إذا كانت جميع العناصر في مصفوفة المفاتيح إما str أو int أو float أو tuple، أو ببساطة من نفس النوع، مع بعض القيود على الأنواع الأساسية.
تجدر الإشارة إلى أن التحقق من أنواع المفاتيح يضيف بعض العمل الإضافي مقدمًا. تفعل بايثون هذا لأنها عادة ما تؤتي ثمارها من خلال جعل الفرز الفعلي أسرع، خاصة بالنسبة للقوائم الطويلة.
يعني هذا عمليًا أنه لكي ينجح هذا التحسين، يجب أن يكون العدد الصحيح أقل منيجب أن لا يكون عددًا كبيرًا
2^30 - 1 (قد يختلف هذا اعتمادًا على النظام الأساسي)
كملاحظة جانبية، إليك مقالة رائعة تشرح كيفية تعامل بايثون مع الأعداد الصحيحة الكبيرة: # كيف تنفذ بايثون الأعداد الصحيحة الطويلة جدًا؟قيود شارع
يجب أن تأخذ جميع أحرف السلسلة أقل من 1 بايت من الذاكرة، مما يعني أنه يجب تمثيلها بقيم عددية في النطاق من 0 إلى 255عمليا، هذا يعني أن السلاسل يجب أن تتكون فقط من الأحرف اللاتينية، والمسافات، وبعض الأحرف الخاصة الموجودة في جدول ASCII.
قيود تعويم
قيود الصفوف
ثانيًا، قد يكون ذكر هذه المعرفة بمثابة لمسة لطيفة في مقابلة مطور بايثون.
أما بالنسبة للتطوير الفعلي للتعليمات البرمجية، فإن فهم هذا التحسين يمكن أن يساعدك على تحسين أداء الفرز.
قم بالتحسين عن طريق تحديد نوع القيم بحكمة
لذا عندما يحين وقت التحسين، قم بتحويل القائمة مثل هذه
floats_and_int = [1.0, -1.0, -0.5, 3]في القائمة التي تبدو هكذا
floats_and_int = [1.0, -1.0, -0.5, 3]قد يؤدي إلى تحسين الأداء.
قم بالتحسين باستخدام المفاتيح لقوائم الكائنات
عند فرز كائنات من فئات مخصصة، تعتمد بايثون على طرق المقارنة التي تحددها، مثل __lt__ (أقل من) أو __gt__ (أكبر من).
ومع ذلك، لا ينطبق التحسين الخاص بالنوع على الفئات المخصصة.
ستستخدم بايثون دائمًا طريقة المقارنة العامة لهذه الكائنات.
إذا كان الأداء أمرًا بالغ الأهمية عند فرز الكائنات المخصصة، ففكر في استخدام وظيفة رئيسية تُرجع نوعًا مضمنًا:
floats_and_int = [1.0, -1.0, -0.5, 3]خاتمة
لا يجب عليك تصميم تطبيقك بالكامل حول تحسينات محددة في CPython، ولكن من الجيد أن تكون على دراية بهذه التحسينات: معرفة أدواتك جيدًا هي وسيلة لتصبح مطورًا أكثر مهارة.
يسمح لك الانتباه إلى مثل هذه التحسينات بالاستفادة منها عندما يستدعي الموقف ذلك، خاصة عندما يصبح الأداء حرجًا:
فكر في سيناريو حيث كان الفرز الخاص بك يعتمد على الطوابع الزمنية: استخدام قائمة متجانسة من الأعداد الصحيحة (الطوابع الزمنية لنظام Unix) بدلاً من كائنات التاريخ والوقت يمكن أن يؤدي إلى الاستفادة من هذا التحسين بشكل فعال.
ومع ذلك، من المهم أن تتذكر أن سهولة قراءة التعليمات البرمجية وقابلية صيانتها يجب أن تكون لها الأولوية على مثل هذه التحسينات.
في حين أنه من المهم معرفة هذه التفاصيل ذات المستوى المنخفض، فمن المهم أيضًا تقدير تجريدات بايثون عالية المستوى التي تجعلها لغة منتجة.
بايثون هي لغة مذهلة، واستكشاف أعماقها يمكن أن يساعدك على فهمها بشكل أفضل وتصبح مبرمج بايثون أفضل.
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3