Sa Python, mayroong pinakamataas na limitasyon sa bilang ng mga recursion (ang maximum na bilang ng mga recursion). Upang magsagawa ng recursive function na may malaking bilang ng mga tawag, kailangang baguhin ang limitasyon. Gamitin ang mga function sa sys module ng karaniwang library.
Ang bilang ng mga recursion ay limitado rin sa laki ng stack. Sa ilang mga kapaligiran, ang resource module ng karaniwang library ay maaaring gamitin upang baguhin ang maximum na laki ng stack (nagtrabaho ito sa Ubuntu, ngunit hindi sa Windows o mac).
Ang sumusunod na impormasyon ay ibinigay dito.
- Kunin ang pinakamataas na limitasyon ng kasalukuyang bilang ng mga recursion:
sys.getrecursionlimit()
- Baguhin ang pinakamataas na limitasyon ng bilang ng mga recursion:
sys.setrecursionlimit()
- Baguhin ang maximum na laki ng stack:
resource.setrlimit()
Ang sample code ay tumatakbo sa Ubuntu.
Kunin ang kasalukuyang limitasyon sa recursion: sys.getrecursionlimit()
Ang kasalukuyang limitasyon ng recursion ay maaaring makuha gamit ang sys.getrecursionlimit().
import sys
import resource
print(sys.getrecursionlimit())
# 1000
Sa halimbawa, ang maximum na bilang ng mga recursion ay 1000, na maaaring mag-iba depende sa iyong kapaligiran. Tandaan na ang mapagkukunang ini-import namin dito ay gagamitin sa ibang pagkakataon, ngunit hindi sa Windows.
Bilang halimbawa, gagamitin namin ang sumusunod na simpleng recursive function. Kung ang isang positibong integer n ay tinukoy bilang isang argumento, ang bilang ng mga tawag ay magiging n beses.
def recu_test(n):
if n == 1:
print('Finish')
return
recu_test(n - 1)
Ang isang error (RecursionError) ay itataas kung susubukan mong magsagawa ng recursion nang higit sa itaas na limitasyon.
recu_test(950)
# Finish
# recu_test(1500)
# RecursionError: maximum recursion depth exceeded in comparison
Tandaan na ang value na nakuha ng sys.getrecursionlimit() ay hindi mahigpit ang maximum na bilang ng mga recursion, ngunit ang maximum stack depth ng Python interpreter, kaya kahit na ang bilang ng mga recursion ay bahagyang mas mababa kaysa sa value na ito, ang isang error (RecursionError) ay Maitaas.
再帰限界は、再帰の限界ではなく、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
Baguhin ang limitasyon ng recursion: sys.setrecursionlimit()
Ang pinakamataas na limitasyon ng bilang ng mga recursion ay maaaring baguhin ng sys.setrecursionlimit(). Ang itaas na limitasyon ay tinukoy bilang isang argumento.
Nagbibigay-daan sa mas malalim na recursion na maisagawa.
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
# 2000
recu_test(1500)
# Finish
Kung ang tinukoy na itaas na limitasyon ay masyadong maliit o masyadong malaki, isang error ang magaganap. Ang hadlang na ito (itaas at mas mababang mga limitasyon ng limitasyon mismo) ay nag-iiba depende sa kapaligiran.
Ang maximum na halaga ng limitasyon ay depende sa platform. Kung kailangan mo ng malalim na recursion, maaari kang tumukoy ng mas malaking halaga sa loob ng hanay na sinusuportahan ng platform, ngunit magkaroon ng kamalayan na ang halagang ito ay magdudulot ng pag-crash kung ito ay masyadong malaki.
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
Ang maximum na bilang ng mga recursion ay nililimitahan din ng laki ng stack, gaya ng ipinaliwanag sa susunod.
Baguhin ang maximum na laki ng stack: resource.setrlimit()
Kahit na ang isang malaking halaga ay nakatakda sa sys.setrecursionlimit(), maaaring hindi ito maisagawa kung ang bilang ng mga recursion ay malaki. Ang isang segmentation fault ay nangyayari tulad ng sumusunod.
sys.setrecursionlimit(10 ** 9)
print(sys.getrecursionlimit())
# 1000000000
recu_test(10 ** 4)
# Finish
# recu_test(10 ** 5)
# Segmentation fault
Sa Python, ang resource module sa karaniwang library ay maaaring gamitin upang baguhin ang maximum na laki ng stack. Gayunpaman, ang resource module ay isang Unix-specific na module at hindi magagamit sa Windows.
- Unix Specific Services — Python 3.10.0 Documentation
- resource — Resource usage information — Python 3.10.0 Documentation
Sa resource.getrlimit(), maaari mong makuha ang limitasyon ng resource na tinukoy sa argument bilang isang tuple ng (soft limit, hard limit). Dito, tinukoy namin ang resource.RLIMIT_STACK bilang resource, na kumakatawan sa maximum na laki ng call stack ng kasalukuyang proseso.
- 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)
Sa halimbawa, ang soft limit ay 8388608 (8388608 B = 8192 KB = 8 MB) at ang hard limit ay -1 (unlimited).
Maaari mong baguhin ang limitasyon ng mapagkukunan gamit ang resource.setrlimit(). Dito, nakatakda rin ang soft limit sa -1 (walang limitasyon). Maaari mo ring gamitin ang patuloy na mapagkukunan.RLIM_INFINIT upang kumatawan sa walang limitasyong limitasyon.
Malalim na recursion, na hindi maisagawa dahil sa segmentation fault bago ang pagbabago ng laki ng stack, ay maaari na ngayong maisagawa.
resource.setrlimit(resource.RLIMIT_STACK, (-1, -1))
print(resource.getrlimit(resource.RLIMIT_STACK))
# (-1, -1)
recu_test(10 ** 5)
# Finish
Dito, ang malambot na limitasyon ay nakatakda sa -1 (walang limitasyon) para sa isang simpleng eksperimento, ngunit sa katotohanan, mas ligtas na limitahan ito sa isang naaangkop na halaga.
Bilang karagdagan, nang sinubukan kong magtakda din ng walang limitasyong malambot na limitasyon sa aking mac, naganap ang sumusunod na error.ValueError: not allowed to raise maximum limit
Ang pagpapatakbo ng script gamit ang sudo ay hindi nakatulong. Maaaring pinaghihigpitan ito ng system.
Ang isang proseso na may epektibong UID ng isang superuser ay maaaring humiling ng anumang makatwirang limitasyon, kabilang ang walang limitasyon.
Gayunpaman, ang isang kahilingan na lumampas sa limitasyon na ipinataw ng system ay magreresulta pa rin sa isang ValueError.
resource.setrlimit() — Resource usage information — Python 3.10.0 Documentation
Walang resource module ang Windows, at hindi mabago ng mac ang maximum na laki ng stack dahil sa mga limitasyon ng system. Kung maaari nating dagdagan ang laki ng stack sa ilang paraan, dapat nating lutasin ang pagkakamali sa segmentation, ngunit hindi pa natin ito nakumpirma.