Python -da, rekursiya sayının üst həddi var (maksimum təkrarlama sayı). Çox sayda zəng ilə rekursiv funksiyanı yerinə yetirmək üçün limiti dəyişdirmək lazımdır. Standart kitabxananın sys modulundakı funksiyalardan istifadə edin.
Yinelemelerin sayı da yığın ölçüsü ilə məhdudlaşır. Bəzi mühitlərdə, standart kitabxananın qaynaq modulu maksimum yığın ölçüsünü dəyişdirmək üçün istifadə edilə bilər (Windows və ya mac -da deyil, Ubuntu -da işləyirdi).
Aşağıdakı məlumatlar burada verilmişdir.
- Mövcud təkrar sayının yuxarı həddini əldə edin:
sys.getrecursionlimit()
- Rekursiya sayının yuxarı həddini dəyişdirin:
sys.setrecursionlimit()
- Yığın maksimum ölçüsünü dəyişdirin:
resource.setrlimit()
Nümunə kodu Ubuntu üzərində işləyir.
Mövcud rekursiya limitini əldə edin: sys.getrecursionlimit ()
Mövcud rekursiya limiti sys.getrecursionlimit () ilə əldə edilə bilər.
import sys
import resource
print(sys.getrecursionlimit())
# 1000
Nümunədə, təkrarlamaların maksimum sayı 1000 -dir, bu mühitinizə görə dəyişə bilər. Diqqət yetirin ki, burada idxal etdiyimiz resurs daha sonra istifadə ediləcək, ancaq Windows -da deyil.
Nümunə olaraq aşağıdakı sadə rekursiv funksiyadan istifadə edəcəyik. Müsbət bir tam n arqument olaraq təyin olunarsa, zənglərin sayı n dəfə olacaq.
def recu_test(n):
if n == 1:
print('Finish')
return
recu_test(n - 1)
Yuxarı həddən artıq rekursiya etməyə çalışsanız bir səhv (RecursionError) ortaya çıxacaq.
recu_test(950)
# Finish
# recu_test(1500)
# RecursionError: maximum recursion depth exceeded in comparison
Qeyd edək ki, sys.getrecursionlimit () ilə əldə edilən dəyər, maksimum rekursiyaların sayı deyil, Python tərcüməçisinin maksimum yığın dərinliyidir, buna görə də rekursiyaların sayı bu dəyərdən bir qədər az olsa belə, bir səhv (RecursionError) qaldırılmaq.
再 帰 は 、 再 帰 の 限界 で は な 、 、 python イ ン タ ー プ リ タ の タ ッ ク の 最大 深度 で す す
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
Rekursiya limitini dəyişdirin: sys.setrecursionlimit ()
Təkrarların sayının yuxarı həddi sys.setrecursionlimit () ilə dəyişdirilə bilər. Üst hədd arqument olaraq göstərilir.
Daha dərin rekursiyanın həyata keçirilməsinə imkan verir.
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
# 2000
recu_test(1500)
# Finish
Göstərilən yuxarı hədd çox kiçik və ya çox böyük olarsa, bir səhv meydana gələcək. Bu məhdudiyyət (həddin özünün yuxarı və aşağı sərhədləri) mühitə görə dəyişir.
Limitin maksimum dəyəri platformadan asılıdır. Dərin bir rekursiyaya ehtiyacınız varsa, platformanın dəstəklədiyi aralığın içərisində daha böyük bir dəyər təyin edə bilərsiniz, ancaq bu dəyərin çox böyük olduğu təqdirdə qəzaya səbəb olacağını unutmayın.
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
Maksimum təkrarlama sayı, aşağıda izah edildiyi kimi yığın ölçüsü ilə də məhdudlaşır.
Yığın maksimum ölçüsünü dəyişdirin: resource.setrlimit ()
Sys.setrecursionlimit () -də böyük bir dəyər təyin olunsa belə, rekursiyaların sayı çox olarsa icra olunmaya bilər. Segmentasiya xətası aşağıdakı kimi baş verir.
sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
recu_test(10 ** 4)
# Finish
# recu_test(10 ** 5)
# Segmentation fault
Python -da, standart kitabxanadakı resurs modulu maksimum yığın ölçüsünü dəyişdirmək üçün istifadə edilə bilər. Bununla birlikdə, qaynaq modulu Unix üçün xüsusi bir moduldur və Windows-da istifadə edilə bilməz.
- Unix Specific Services — Python 3.10.0 Documentation
- resource — Resource usage information — Python 3.10.0 Documentation
Resource.getrlimit () ilə arqumentdə göstərilən mənbənin həddini (yumşaq limit, sərt limit) bir dəstə olaraq əldə edə bilərsiniz. Burada, cari prosesin zəng yığınının maksimum ölçüsünü əks etdirən resurs olaraq resource.RLIMIT_STACK təyin edirik.
- 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)
Nümunədə yumşaq limit 8388608 (8388608 B = 8192 KB = 8 MB) və sərt limit -1 (məhdudiyyətsiz) təşkil edir.
Resurs limitini resource.setrlimit () ilə dəyişə bilərsiniz. Burada yumşaq limit də -1 (məhdudiyyətsiz) olaraq təyin olunur. Limitsiz limiti təmsil etmək üçün daimi resursdan istifadə edə bilərsiniz.RLIM_INFINIT.
Yığın ölçüsü dəyişməzdən əvvəl seqmentləşdirmə xətası səbəbindən həyata keçirilə bilməyən dərin rekursiya artıq həyata keçirilə bilər.
resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))
print(resource.getrlimit(resource.RLIMIT_STACK))
# (-1, -1)
recu_test(10 ** 5)
# Finish
Burada yumşaq limit sadə bir sınaq üçün -1 (məhdudiyyətsiz) olaraq təyin edilir, amma əslində onu uyğun bir dəyərlə məhdudlaşdırmaq daha təhlükəsiz olar.
Əlavə olaraq, mac -da da məhdudiyyətsiz bir məhdudiyyət qoymağa çalışdığım zaman aşağıdakı səhv baş verdi.ValueError: not allowed to raise maximum limit
Ssenarini sudo ilə işlətmək kömək etmədi. Sistem tərəfindən məhdudlaşdırıla bilər.
Bir super istifadəçinin təsirli UID’si olan bir proses, heç bir məhdudiyyət daxil olmaqla, hər hansı bir ağlabatan limit tələb edə bilər.
Bununla birlikdə, sistem tərəfindən qoyulan limiti aşan bir sorğu yenə də ValueError ilə nəticələnəcək.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation
Windows-un resurs modulu yoxdur və mac sistem məhdudiyyətləri səbəbindən maksimum yığın ölçüsünü dəyişə bilmədi. Əgər hansısa vasitələrlə yığının ölçüsünü artıra bilsək, seqmentasiya xətasını həll edə bilməliyik, lakin bunu təsdiq edə bilməmişik.