في بايثون ، يوجد حد أعلى لعدد العودية (الحد الأقصى لعدد العودية). لتنفيذ وظيفة تكرارية مع عدد كبير من المكالمات ، من الضروري تغيير الحد. استخدم الوظائف الموجودة في الوحدة النمطية sys للمكتبة القياسية.
عدد العودية محدود أيضًا بحجم المكدس. في بعض البيئات ، يمكن استخدام وحدة الموارد للمكتبة القياسية لتغيير الحد الأقصى لحجم المكدس (عملت على Ubuntu ، ولكن ليس على Windows أو mac).
يتم توفير المعلومات التالية هنا.
- احصل على الحد الأعلى للعدد الحالي من العودية:
sys.getrecursionlimit()
- تغيير الحد الأعلى لعدد العودية:
sys.setrecursionlimit()
- قم بتغيير الحجم الأقصى للمكدس:
resource.setrlimit()
نموذج التعليمات البرمجية قيد التشغيل على أوبونتو.
احصل على حد العودية الحالي: sys.getrecursionlimit ()
يمكن الحصول على حد العودية الحالي باستخدام sys.getrecursionlimit ().
import sys
import resource
print(sys.getrecursionlimit())
# 1000
في المثال ، الحد الأقصى لعدد العودية هو 1000 ، والتي قد تختلف حسب بيئتك. لاحظ أن المورد الذي نستورده هنا سيتم استخدامه لاحقًا ، ولكن ليس على Windows.
كمثال ، سوف نستخدم الدالة العودية البسيطة التالية. إذا تم تحديد عدد صحيح موجب n كوسيطة ، فسيكون عدد المكالمات n مرة.
def recu_test(n):
if n == 1:
print('Finish')
return
recu_test(n - 1)
سيظهر خطأ (RecursionError) إذا حاولت تنفيذ العودية أكثر من الحد الأعلى.
recu_test(950)
# Finish
# recu_test(1500)
# RecursionError: maximum recursion depth exceeded in comparison
لاحظ أن القيمة التي تم الحصول عليها بواسطة sys.getrecursionlimit () ليست بالضبط الحد الأقصى لعدد العودية ، ولكن الحد الأقصى لعمق المكدس لمترجم Python ، لذلك حتى إذا كان عدد العادات أقل قليلاً من هذه القيمة ، فإن الخطأ (RecursionError) سوف تثار.
再 帰 限界 は 、 再 帰 の 限界 で は な く 、 بيثون イ ン タ ー プ リ タ の タ タ ッ ク の 最大 深度 で す。
python – Max recursion is not exactly what sys.getrecursionlimit() claims. How come? – Stack Overflow
# recu_test(995)
# RecursionError: maximum recursion depth exceeded while calling a Python object
تغيير حد العودية: sys.setrecursionlimit ()
يمكن تغيير الحد الأعلى لعدد العودية بواسطة sys.setrecursionlimit (). يتم تحديد الحد الأعلى كوسيطة.
يسمح بإجراء عملية عودية أعمق.
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
# 2000
recu_test(1500)
# Finish
إذا كان الحد الأعلى المحدد صغيرًا جدًا أو كبيرًا جدًا ، فسيحدث خطأ. يختلف هذا القيد (الحدود العليا والسفلى للحد نفسه) تبعًا للبيئة.
يعتمد الحد الأقصى لقيمة الحد على النظام الأساسي. إذا كنت بحاجة إلى تكرار عميق ، فيمكنك تحديد قيمة أكبر ضمن النطاق الذي تدعمه المنصة ، ولكن كن على دراية بأن هذه القيمة ستتسبب في حدوث عطل إذا كانت كبيرة جدًا.
If the new limit is too low at the current recursion depth, a RecursionError exception is raised.
sys.setrecursionlimit() — System-specific parameters and functions — Python 3.10.0 Documentation
sys.setrecursionlimit(4)
print(sys.getrecursionlimit())
# 4
# sys.setrecursionlimit(3)
# RecursionError: cannot set the recursion limit to 3 at the recursion depth 1: the limit is too low
sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
# sys.setrecursionlimit(10 ** 10)
# OverflowError: signed integer is greater than maximum
الحد الأقصى لعدد العودية محدود أيضًا بحجم المكدس ، كما هو موضح لاحقًا.
قم بتغيير الحجم الأقصى للمكدس: Resource.setrlimit ()
حتى إذا تم تعيين قيمة كبيرة في sys.setrecursionlimit () ، فقد لا يتم تنفيذها إذا كان عدد عمليات العودية كبيرًا. يحدث خطأ تجزئة على النحو التالي.
sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
recu_test(10 ** 4)
# Finish
# recu_test(10 ** 5)
# Segmentation fault
في Python ، يمكن استخدام وحدة الموارد في المكتبة القياسية لتغيير الحد الأقصى لحجم المكدس. ومع ذلك ، فإن وحدة الموارد هي وحدة خاصة بنظام Unix ولا يمكن استخدامها على Windows.
- Unix Specific Services — Python 3.10.0 Documentation
- resource — Resource usage information — Python 3.10.0 Documentation
باستخدام Resource.getrlimit () ، يمكنك الحصول على حد المورد المحدد في الوسيطة كمجموعة من (soft limit، hard limit). هنا ، نحدد Resource.RLIMIT_STACK كمورد ، والذي يمثل الحجم الأقصى لمكدس الاستدعاءات للعملية الحالية.
- resource.getrlimit() — Resource usage information — Python 3.10.0 Documentation
- resource.RLIMIT_STACK — Resource usage information — Python 3.10.0 Documentation
print(resource.getrlimit(resource.RLIMIT_STACK))
# (8388608, -1)
في المثال ، الحد المرن هو 8388608 (8388608 B = 8192 كيلوبايت = 8 ميجابايت) والحد الأقصى هو -1 (غير محدود).
يمكنك تغيير حد المورد باستخدام Resource.setrlimit (). هنا ، يتم تعيين الحد المرن أيضًا على -1 (بلا حدود). يمكنك أيضًا استخدام المورد الثابت .RLIM_INFINIT لتمثيل الحد غير المحدود.
يمكن الآن إجراء العودية العميقة ، والتي لا يمكن إجراؤها بسبب خطأ تجزئة قبل تغيير حجم المكدس.
resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))
print(resource.getrlimit(resource.RLIMIT_STACK))
# (-1, -1)
recu_test(10 ** 5)
# Finish
هنا ، يتم تعيين الحد المرن على -1 (بلا حدود) لتجربة بسيطة ، ولكن في الواقع ، سيكون من الأكثر أمانًا قصره على قيمة مناسبة.
بالإضافة إلى ذلك ، عندما حاولت تعيين حد ضعيف غير محدود على جهاز Mac الخاص بي أيضًا ، حدث الخطأ التالي.ValueError: not allowed to raise maximum limit
تشغيل البرنامج النصي باستخدام sudo لم يساعد. قد يكون مقيدًا من قبل النظام.
يمكن للعملية ذات المعرف الفريد الفعال للمستخدم المتميز أن تطلب أي حد معقول ، بما في ذلك عدم وجود حد.
ومع ذلك ، فإن الطلب الذي يتجاوز الحد الذي يفرضه النظام سيظل ينتج عنه خطأ في القيمة.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation
لا يحتوي Windows على وحدة موارد ، ولا يمكن لنظام mac تغيير الحد الأقصى لحجم المكدس بسبب قيود النظام. إذا تمكنا من زيادة حجم المكدس ببعض الوسائل ، فسنكون قادرين على حل خطأ التجزئة ، لكننا لم نتمكن من تأكيد ذلك.