شرحنا في المقال السابق أهم الأسئلة النظرية التي قد تُطرح على المتقدمين لوظيفة مطور بايثون خلال مقابلة التوظيف، وسنوضح في هذا المقال أهم الأسئلة والتمارين العملية التي قد تُطلب منك فوريًا في مقابلات التوظيف بوظيفة مطور بايثون.
قد تُطرح في المقابلات التقنية بعض الأسئلة التي تتطلب تحسين أو تصحيح شيفرة برمجية، سنذكر أهمها في ما يلي.
التمرين الأول: تحسين الشيفرة
قد يحتوي التمرين على أسئلة من نوع:
-
اشرح وظيفة الدالة
process_numbers
في المثال التالي وما هو الخرج؟ - ما هي العملية التي يمكن التخلي عنها دون أن يؤثر ذلك في الخرج؟
def process_numbers(numbers): unique_numbers = list(set(numbers)) unique_numbers.sort() unique_tuple = tuple(unique_numbers) total = sum(unique_tuple) average = total / len(unique_tuple) if unique_tuple else 0 return [num for num in unique_tuple if num > average] print(process_numbers([7,1,3,4,2,3,5,6,4]))
وتكون الإجابة على النحو الآتي:
-
الجواب 1: تقبل الدالة السابقة وسيطًا على شكل قائمة list مكونة من أعداد ثم تختار العناصر الفريدة منها وتوجِد متوسطها الحسابي، ثم تعيد قائمةً تضم الأعداد الفريدة الأكبر تمامًا من المتوسط. وسيكون الخرج
[7, 6, 5]
- الجواب 2: عملية تحويل القائمة List إلى قائمة Tuple في السطر الرابع
التمرين الثاني: استخدام مكتبات بايثون مقارنة بالتنفيذ اليدوي لخوارزمية
قد يحتوي التمرين على أسئلة من نوع:
- ما وظيفة الشيفرة في هذا التمرين؟
- هل يمكنك تنفيذ نفس الوظيفة باستخدام مكتبات جاهزة؟
- اكتب شيفرةً تقارن بين زمني تنفيذ الطريقتين السابقتين، ما الذي تلاحظه مع الازدياد الكبير لحجم قائمة البيانات؟
import random random_data = set(random.sample(range(1, 10000), 1000)) def calculate_median(data): data = list(data) data.sort() n = len(data) mid = n // 2 if n % 2 == 1: return data[mid] else: return (data[mid - 1] + data[mid]) / 2
وتكون الإجابة كالآتي:
- الجواب الأول: تعطي الشيفرة السابقة طريقة حساب وسيط Median لعينة من الأرقام بطريقة يدوية
-
الجواب الثاني: نعم، باستخدام المكتبة
statistics
أوscipy
-
الجواب الثالث: باستخدام المكتبة
time
import random import time import statistics random_data = set(random.sample(range(1, 10000), 1000)) # تنفيذ يدوي للخوارزمية def calculate_median(data): data = list(data) data.sort() n = len(data) mid = n // 2 if n % 2 == 1: return data[mid] else: return (data[mid - 1] + data[mid]) / 2 # Statistics استخدام المكتبة def median_using_statistics(data): return statistics.median(data) # تقدير وقت التنفيذ start_manual = time.time() calculate_median(random_data) end_manual = time.time() start_Statistics = time.time() median_using_statistics(random_data) end_Statistics = time.time() # طباعة النتائج print("Manual Sort-Based Time:", end_manual - start_manual) print("Statistics-Based Time:", end_Statistics - start_Statistics)
يمكن ملاحظة أنه مع ازدياد حجم البيانات، يصبح وقت التنفيذ أكبر بكثير في حال الطريقة اليدوية، لأن المكتبات تكون محققة باستخدام خوارزميات أسرع وأمثل وتعمل بطريقة أكثر كفاءة، مما يجعل وقت تنفيذها أقل أو أكثر استقرارًا مقارنةً بالأسلوب اليدوي.
التمرين الثالث: استخدام المكتبة numpy
قد يحتوي التمرين على أسئلة من نوع:
-
أوجد الخطأ في الشيفرة التالية -لا بد من امتلاك خلفية باستخدام المكتبة
numpy
- فسّر الخطأ
- صحح الخطأ، واكتب الشيفرة الصحيحة
import numpy as np def transform_array(arr): arr[arr < 0] = np.nan # NaN استبدل القيم السالبة بقيمة من النوع mean_value = np.nanmean(arr) # NaN احسب المتوسط مهملًا القيم arr = arr / mean_value # سوّي عناصرالمصفوفة بالقسمة على المتوسط return arr data = np.array([3, -1, 7, -5, 10]) print(transform_array(data))
يكون الجواب على النحو الآتي:
- الجواب الأول: الخطأ في السطر الثالث
-
الجواب الثاني: لا تدعم
numpy
تخزين القيمNaN
ضمن المصفوفات الصحيحة - الجواب الثالث: علينا تحويل عناصر المصفوفة صراحة إلى النوع float قبل استبدال الأعداد السالبة
import numpy as np def transform_array(arr): arr = arr.astype(float) # float حوّل عناصر المصفوفة إلى النوع arr[arr < 0] = np.nan . . . data = np.array([3, -1, 7, -5, 10]) print(transform_array(data))
التمرين الرابع: استخدام المكتبة pandas
قد يحتوي التمرين على أسئلة من نوع:
-
أوجد الخطأ في الشيفرة التالية التي تستخدم المكتبة
pandas
- فسّر الخطأ
- صحح الخطأ الموجود بالشيفرة، واكتب الشيفرة الصحيحة
import pandas as pd data = {'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]} df = pd.DataFrame(data) df['C'] = df.A * 2 # C أنشئ عمود جديد filtered_df = df[df.C > 5] # أكبر من 5 C احذف الصف عندما تكون القيمة في filtered_df.reset_index() # أعد ضبط فهرس إطار البيانات print(filtered_df)
ويكون الجواب على النحو الآتي:
- الجواب الأول: الخطأ في السطر السادس
-
الجواب الثاني: لن تتغير الفهرسة بعد حذف الصفوف ولن تُطبق على
filtered_df
-
الجواب الثالث: علينا استدعاء التابع
()reset_index
باستخدامinplace=true
على النحو:
filtered_df.reset_index(drop=True, inplace=True)
التمرين الخامس: الاستيثاق والثغرات الأمنية
تحاول الشيفرة التالية الاستيثاق باستخدام JWT، لكنها تعاني من ثغرة أمنية خطيرة والمطلوب:
- حدد الثغرة الأمنية في هذه الشيفرة
- اقترح حلًا لها
import jwt import datetime SECRET_KEY = "supersecretkey" def generate_token(username): payload = { "user": username, "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=30) } return jwt.encode(payload, SECRET_KEY, algorithm="HS256") def verify_token(token): try: decoded = jwt.decode(token, SECRET_KEY, algorithms="HS256") return decoded["user"] except Exception as e: return None
وللإجابة عن هذه التساؤلات، سيكون الجواب الأول أن هذه الشيفرة معرضة لهجوم خلط الخوارزميات Algorithm Confusion Attack، نظرًا لإمكانية تعديل المخترق على ترويسة الطلب ببساطة ويلغي استخدام خوارزمية HS256
إلى none
وبالتالي يتسلل دون استيثاق
أما الحل السريع وهو جواب السؤال الثاني، فيتمثل في إجبار استخدام خوارزمية ضمن الدالة verify_token
والتقاط الأخطاء الناتجة. فيما يلي الشيفرة المعدلة لهذه الدالة:
def verify_token(token): try: # صرّح عن خوارزمية التشفير المتوقعة من المفتاح decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) return decoded["user"] except jwt.ExpiredSignatureError: return "Token expired!" except jwt.InvalidTokenError: return "Invalid token!"
نصائح للاستعداد لمقابلة العمل
من أجل الاستعداد الجيد لمقابلة العمل كمطور بايثون، لا بد من التأكد من اعتماد النصائح الآتية:
فهم ما نتعلمه
من المهم استيعاب الغاية من كل قاعدة ومبدأ وتقنية وتدوين الملاحظات حول الاستخدام الأمثل الذي وجدناه لها. يحتاج أي مطور بايثون إلى سؤال نفسه: لماذا تقدم بايثون مثلًا عدة بنىً مختلفة لتجميع البيانات مثل list
و tuple
و range
؟ وما الغاية من كل منها؟ وأين يكمن الاستخدام الأمثل لها؟ هذه التساؤلات، ستساعد كل متقدم للوظيفة على تهيئة نفسه للإجابة بدقة واختصار على الأسئلة المطروحة عليه.
التحليل والمقارنة
لا بد من التحليل والمقارنة سواء باستخدام تعليمات مختلفة أو خوارزمية مختلفة، خاصة عند موااجهة مقاربات مختلفة لحل المشكلة نفسها. علينا أن نفهم كل نهج بدقة وندوّن ملاحظاتنا عليه، ثم نضيف رأينا الخاص ونشرح لأنفسنا ما يجري وما هو الاستخدام الأمثل الذي وجدناه.
تطبيق أفضل الممارسات
كل منا حر في صياغة الكود البرمجي الخاص به بالطريقة التي يجدها مناسبة، لكن لنتخيل أن يفعل ذلك كل عضو من أعضاء فريق العمل؟ ستكون الامور فوضوية ومربكة لذا علينا أن نعود نفسنا على تطبيق أفضل الممارسات التي يُنصح بها أثناء بناء المشاريع، إذ سيسهّل هذا الأمر الاندماج لاحقًا ضمن أي فريق عمل خاصة في الشركات التي تأخذ تطبيق أفضل الممارسات في كتابة وتنسيق وصيانة الشيفرة على محمل الجد دائمًا. يمكن قراءة مقال كيف تكتب كود أنيق وسهل القراءة باستخدام لغة بايثون للمساعدة بذلك.
التركيز على المهارات المطلوبة في العمل
لا أحد منا كامل، فقد نمتلك بعضًا من المهارات المطلوبة وينقصنا بعضها، لكن من المهم أن لا نشعر بالإحباط، وأن نحاول تعزيز معارفنا وخبراتنا بالاطلاع على مراجع مفيدة والمراجع كثيرة ومتنوعة، ويمكن هنا الاستفادة من مقالات أكاديمية حسوب حول بايثون، إلى جانب الكتب البرمجية التي تساعد على التعلم بطريقة منهجية منظمة.
ختامًا
بهذا نكون قد قدمنا في هذا المقال ما ينبغي على المتقدم لوظيفة مطور بايثون أن يحضّره ويتذكر تفاصيله قبل الوصول إلى مقابلة العمل، ثم عرضنا بعضًا من الأسئلة التي قد تُطرح عليه أثناء المقابلة.
المراجع
- توثيق بايثون باللغة العربية على موقع موسوعة حسوب
- كتاب البرمجة بلغة بايثون من إعداد أكاديمية حسوب
- Advance Concepts of Python for Python Developer
- Advanced Python Tutorials: Dive into Complex Concepts
- ( advanced Python interview questions (and answers
- Python Coding Interview Questions (Beginner to Advanced)
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.