Python’da özyineleme sayısının bir üst sınırı vardır (maksimum özyineleme sayısı). Çok sayıda çağrı ile özyinelemeli bir işlevi yürütmek için limiti değiştirmek gerekir. Standart kitaplığın sys modülündeki işlevleri kullanın.
Özyineleme sayısı da yığın boyutu ile sınırlıdır. Bazı ortamlarda, standart kitaplığın kaynak modülü maksimum yığın boyutunu değiştirmek için kullanılabilir (Ubuntu’da çalıştı, ancak Windows veya mac’ta çalışmadı).
Aşağıdaki bilgiler burada verilmiştir.
- Geçerli yineleme sayısının üst sınırını alın:
sys.getrecursionlimit()
- Özyineleme sayısının üst sınırını değiştirin:
sys.setrecursionlimit()
- Yığının maksimum boyutunu değiştirin:
resource.setrlimit()
Örnek kod Ubuntu’da çalışıyor.
Geçerli özyineleme sınırını alın: sys.getrecursionlimit()
Geçerli özyineleme sınırı, sys.getrecursionlimit() ile elde edilebilir.
import sys
import resource
print(sys.getrecursionlimit())
# 1000
Örnekte, ortamınıza bağlı olarak değişebilen maksimum yineleme sayısı 1000’dir. Buraya aktardığımız kaynağın daha sonra kullanılacağını, ancak Windows’ta kullanılamayacağını unutmayın.
Örnek olarak, aşağıdaki basit özyinelemeli işlevi kullanacağız. Argüman olarak pozitif bir n tamsayı belirtilirse, çağrı sayısı n kez olacaktır.
def recu_test(n):
if n == 1:
print('Finish')
return
recu_test(n - 1)
Üst sınırdan fazla özyineleme yapmaya çalışırsanız bir hata (RecursionError) ortaya çıkar.
recu_test(950)
# Finish
# recu_test(1500)
# RecursionError: maximum recursion depth exceeded in comparison
sys.getrecursionlimit() tarafından elde edilen değerin kesinlikle maksimum özyineleme sayısı değil, Python yorumlayıcısının maksimum yığın derinliği olduğuna dikkat edin, bu nedenle özyineleme sayısı bu değerden biraz daha az olsa bile, bir hata (RecursionError) olacaktır. yükseltilecek.
再帰限界は、再帰の限界ではなく、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
Özyineleme sınırını değiştir: sys.setrecursionlimit()
Özyineleme sayısının üst sınırı sys.setrecursionlimit() tarafından değiştirilebilir. Üst sınır bir argüman olarak belirtilir.
Daha derin özyinelemenin gerçekleştirilmesine izin verir.
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
# 2000
recu_test(1500)
# Finish
Belirtilen üst limit çok küçük veya çok büyük ise hata oluşur. Bu kısıtlama (sınırın kendisinin üst ve alt limitleri) ortama bağlı olarak değişir.
Maksimum limit değeri platforma bağlıdır. Derin özyinelemeye ihtiyacınız varsa, platform tarafından desteklenen aralık içinde daha büyük bir değer belirtebilirsiniz, ancak bu değerin çok büyük olması durumunda çökmeye neden 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
Azami özyineleme sayısı ayrıca aşağıda açıklandığı gibi yığın boyutuyla da sınırlıdır.
Yığının maksimum boyutunu değiştirin: resource.setrlimit()
sys.setrecursionlimit() içinde büyük bir değer ayarlansa bile, özyineleme sayısı büyükse yürütülmeyebilir. Aşağıdaki gibi bir segmentasyon hatası oluşur.
sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
recu_test(10 ** 4)
# Finish
# recu_test(10 ** 5)
# Segmentation fault
Python’da, maksimum yığın boyutunu değiştirmek için standart kitaplıktaki kaynak modülü kullanılabilir. Ancak kaynak modülü, Unix’e özgü bir modüldür ve Windows’ta kullanılamaz.
- Unix Specific Services — Python 3.10.0 Documentation
- resource — Resource usage information — Python 3.10.0 Documentation
resource.getrlimit() ile, bağımsız değişkende belirtilen kaynağın sınırını (yumuşak limit, sabit limit) demeti olarak alabilirsiniz. Burada, mevcut işlemin çağrı yığınının maksimum boyutunu temsil eden kaynak olarak resource.RLIMIT_STACK’i belirtiyoruz.
- 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)
Örnekte, yumuşak limit 8388608 (8388608 B = 8192 KB = 8 MB) ve sabit limit -1’dir (sınırsız).
Resource.setrlimit() ile kaynağın limitini değiştirebilirsiniz. Burada, yumuşak limit de -1 (sınır yok) olarak ayarlanmıştır. Sınırsız limiti temsil etmek için sabit resource.RLIM_INFINIT’i de kullanabilirsiniz.
Yığın boyutu değişikliğinden önce segmentasyon hatası nedeniyle gerçekleştirilemeyen derin özyineleme artık gerçekleştirilebilir.
resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))
print(resource.getrlimit(resource.RLIMIT_STACK))
# (-1, -1)
recu_test(10 ** 5)
# Finish
Burada, basit bir deney için yumuşak sınır -1 (sınır yok) olarak ayarlanır, ancak gerçekte bunu uygun bir değerle sınırlamak daha güvenli olacaktır.
Ayrıca mac’uma da sınırsız soft limit koymaya çalıştığımda aşağıdaki hata oluştu.ValueError: not allowed to raise maximum limit
Komut dosyasını sudo ile çalıştırmak yardımcı olmadı. Sistem tarafından kısıtlanmış olabilir.
Bir süper kullanıcının etkin UID’sine sahip bir süreç, limitsiz olmak üzere herhangi bir makul limit talep edebilir.
Ancak, sistem tarafından belirlenen sınırı aşan bir istek yine de ValueError ile sonuçlanacaktır.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation
Windows’ta bir kaynak modülü yoktur ve mac, sistem sınırlamaları nedeniyle maksimum yığın boyutunu değiştiremedi. Yığın boyutunu bir şekilde artırabilirsek, segmentasyon hatasını çözebiliriz, ancak bunu onaylayamadık.