بايثون العرب
10.5K subscribers
866 photos
183 videos
768 links
Download Telegram
⚡️ تسريع الدوال باستخدام functools.lru_cache في بايثون

هل تعاني من بطء بعض الدوال في برنامجك؟ استخدم `lru_cache` من مكتبة `functools` لتخزين نتائج استدعاءات الدوال المتكررة وتسريع الأداء بشكل ملحوظ.

from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(30))
print(fibonacci(30)) # This call will be much faster due to caching


المُزخرف `@lru_cache(maxsize=None)` يقوم بتخزين نتائج استدعاء الدالة `fibonacci` بناءً على وسائطها. عند استدعاء الدالة مرة أخرى بنفس الوسائط، يتم إرجاع النتيجة المخزنة بدلاً من إعادة حسابها، مما يحسن الأداء بشكل كبير للدوال التي تُستدعى بنفس المدخلات عدة مرات.

['#بايثون', '#برمجة', '#functools', '#lru_cache', '#تحسين_الأداء', '#Python', '#Programming', '#Performance']
💡 حل مشكلة الـ GIL (Global Interpreter Lock) نظرياً 💡

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

import threading
import time

def worker(num):
"""دالة بسيطة لتوضيح استهلاك الوقت"""
for i in range(num):
time.sleep(0.01)
# هنا يمكن أن يحدث استهلاك لوحدة المعالجة المركزية (CPU-bound)

# مثال توضيحي (بدون معالجة GIL فعلياً، فقط للتوضيح)
print("بدء التنفيذ...")
start_time = time.time()

threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(100,))
threads.append(t)
t.start()

for t in threads:
t.join()

end_time = time.time()
print(f"انتهى التنفيذ في: {end_time - start_time:.2f} ثانية")


الـ GIL (Global Interpreter Lock) هو آلية في CPython تمنع أكثر من thread واحد من تنفيذ bytecode بايثون في نفس الوقت داخل عملية واحدة. هذا يعني أن الـ threads المتعددة لا تعمل بالتوازي الحقيقي على معالجات متعددة إذا كانت تقوم بعمليات مرتبطة بوحدة المعالجة المركزية (CPU-bound). لحل هذه المشكلة نظرياً، نلجأ إلى استخدام العمليات (processes) بدلاً من الـ threads (باستخدام مكتبة `multiprocessing`)، أو الاعتماد على مكتبات خارجية لا تعتمد على الـ GIL (مثل NumPy)، أو استخدام لغات أخرى مدمجة مع بايثون (مثل Cython).

['#بايثون', '#GIL', '#برمجة', '#تطوير', '#PythonTips', '#Performance']
✨ تحسين أداء Python: فهم GIL

هل تساءلت يومًا لماذا لا تستفيد بعض برامج Python متعددة الخيوط (multithreaded) بشكل كامل من جميع أنوى المعالج؟ الجواب غالبًا ما يكون في 'Global Interpreter Lock' (GIL). دعنا نتعمق في هذا المفهوم!

import threading
import time

def worker(num):
"""دالة عامل بسيطة تحاكي العمل"""
print(f'Worker {num} started')
time.sleep(1)
print(f'Worker {num} finished')

threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()

for t in threads:
t.join()

print('All workers done.')


في CPython (التنفيذ الأكثر شيوعًا لبايثون)، يمنع GIL خيطين (threads) من تنفيذ بايت كود بايثون في نفس الوقت داخل عملية واحدة. هذا يعني أنه حتى لو كان لديك معالج متعدد النوى، فلن يتمكن إلا خيط واحد من تشغيل كود بايثون في أي لحظة معينة. هذا لا يؤثر على العمليات التي تعتمد على I/O (مثل قراءة الملفات أو الشبكات) لأن GIL يتم تحريره أثناء انتظار عمليات I/O، ولكنه يحد من التوازي الحقيقي لعمليات CPU-bound. لحل هذه المشكلة، غالبًا ما يتم استخدام عمليات (processes) بدلاً من الخيوط، حيث أن كل عملية لها مترجم بايثون خاص بها وبالتالي GIL الخاص بها.

['#Python', '#برمجة', '#GIL', '#تطوير', '#نصائح_بايثون', '#Performance']
🚀 تحسين أداء Python: فهم GIL

هل تساءلت يومًا لماذا قد لا تستفيد برامج Python المتعددة الخيوط (multithreaded) بشكل كامل من المعالجات متعددة النوى؟ 🤔 دعنا نتعمق في Global Interpreter Lock (GIL) وكيف يؤثر على أداء Python.

import threading
import time

def count_down(n):
while n > 0:
n -= 1

start_time = time.time()

# بدون GIL (نظريًا، في CPython هو موجود)
# يمكن تشغيل هذه المهام بالتوازي الحقيقي على نوى مختلفة

thread1 = threading.Thread(target=count_down, args=(10000000,))
thread2 = threading.Thread(target=count_down, args=(10000000,))

thread1.start()
thread2.start()

thread1.join()
thread2.join()

end_time = time.time()
print(f"الوقت المستغرق: {end_time - start_time:.4f} ثانية")

# ملاحظة: في CPython، بسبب GIL، ستعمل هذه الخيوط بشكل تسلسلي غالبًا،
# مما يحد من الاستفادة من المعالجات متعددة النوى للمهام التي تستهلك وحدة المعالجة المركزية.


Global Interpreter Lock (GIL) هو آلية في CPython (التنفيذ الأكثر شيوعًا لبايثون) تمنع أكثر من خيط واحد (thread) من تنفيذ بايت كود Python في نفس الوقت داخل عملية واحدة. هذا يعني أنه حتى لو كان لديك معالج متعدد النوى، فإن خيوط Python التي تستهلك وحدة المعالجة المركزية (CPU-bound) لن تعمل بالتوازي الحقيقي. بالنسبة للمهام التي تعتمد على الإدخال/الإخراج (I/O-bound)، مثل قراءة الملفات أو طلبات الشبكة، يكون GIL أقل تأثيرًا لأنه يحرر القفل أثناء انتظار عمليات الإدخال/الإخراج.

['#Python', '#GIL', '#Programming', '#Performance', '#Multithreading', '#CPython', '#Tips', '#Tutorial']
✨ تحسين أداء Python: فهم GIL 🐍

هل تساءلت يومًا لماذا قد لا تستفيد برامج Python متعددة الخيوط (multithreaded) بشكل كامل من وحدات المعالجة المركزية (CPU) متعددة النوى؟ الجواب يكمن في Global Interpreter Lock (GIL). دعنا نتعمق!

import threading
import time

def countdown(n):
while n > 0:
n -= 1

start_time = time.time()
# تشغيل دالتين في خيطين منفصلين (ولكن GIL يحد من التوازي الحقيقي)
thread1 = threading.Thread(target=countdown, args=(10000000,))
thread2 = threading.Thread(target=countdown, args=(10000000,))

thread1.start()
thread2.start()

thread1.join()
thread2.join()

end_time = time.time()
print(f"الوقت المستغرق: {end_time - start_time:.4f} ثانية")


Global Interpreter Lock (GIL) هو آلية في CPython (التطبيق الأكثر شيوعًا لبايثون) تمنع خيطًا واحدًا فقط من تنفيذ كود بايثون في كل مرة، حتى على المعالجات متعددة النوى. هذا يعني أنه بالنسبة للمهام التي تعتمد بكثافة على وحدة المعالجة المركزية (CPU-bound)، فإن استخدام الخيوط المتعددة قد لا يؤدي إلى تسريع كبير. للحصول على توازي حقيقي للمهام التي تعتمد على وحدة المعالجة المركزية، فكر في استخدام وحدات (multiprocessing) بدلاً من الخيوط (threading).

['#Python', '#GIL', '#Programming', '#CPython', '#Multithreading', '#Performance', '#Tips']
💡 تحسين أداء Python مع `collections.deque` 🚀

هل تبحث عن طريقة أسرع لإضافة أو إزالة عناصر من طرفي قائمة في Python؟ تعرف على `collections.deque` وكيف يمكن أن يحدث فرقًا كبيرًا!

from collections import deque

# إنشاء deque
d = deque(['a', 'b', 'c'])

# إضافة عنصر إلى اليسار
d.appendleft('x')

# إضافة عنصر إلى اليمين
d.append('y')

# إزالة عنصر من اليسار
left_item = d.popleft()

# إزالة عنصر من اليمين
right_item = d.pop()

print(d)
print(f"Element removed from left: {left_item}")
print(f"Element removed from right: {right_item}")


`collections.deque` (double-ended queue) هي بنية بيانات محسّنة لعمليات الإضافة والحذف السريعة من كلا الطرفين (اليسار واليمين). على عكس القوائم العادية، لا تتطلب `deque` إعادة ترتيب العناصر عند الإضافة أو الحذف من البداية، مما يجعلها أسرع بكثير لهذه العمليات.

['#Python', '#برمجة', '#تطوير', '#نصائح_برمجية', '#collections', '#deque', '#Performance']
🐍 تحسين أداء Python: دليل سريع للمبتدئين

هل تريد جعل أكواد Python الخاصة بك أسرع وأكثر كفاءة؟ إليك بعض النصائح الأساسية التي ستساعدك على البدء!

def sum_list_naive(numbers):
total = 0
for num in numbers:
total += num
return total

import timeit

my_list = list(range(1000000))

time_naive = timeit.timeit(lambda: sum_list_naive(my_list), number=100)

print(f"الوقت المستغرق للطريقة البسيطة: {time_naive:.6f} ثانية")

def sum_list_optimized(numbers):
return sum(numbers)

time_optimized = timeit.timeit(lambda: sum_list_optimized(my_list), number=100)

print(f"الوقت المستغرق للطريقة المحسنة: {time_optimized:.6f} ثانية")


في هذا المثال، نقارن بين طريقة يدوية لجمع عناصر قائمة وطريقة استخدام الدالة المدمجة `sum()`. كما ترى، الدالة المدمجة أسرع بكثير لأنها مكتوبة بلغة C ومُحسّنة للغاية. القاعدة العامة: استخدم الدوال المدمجة والمكتبات القياسية كلما أمكن ذلك لضمان أفضل أداء.

['#Python', '#برمجة', '#تطوير', '#تعلم_البرمجة', '#PythonTips', '#Performance']