Python 使用全局变量在exec()级别递归

Python 使用全局变量在exec()级别递归,python,python-3.x,recursion,global-variables,Python,Python 3.x,Recursion,Global Variables,在无意中发现exec()之后,我一直在玩弄exec(),以便更好地理解它的工作原理。我试图让这个讨厌的脚本增加一个全局变量,读取自身,并用新的全局值调用exec,直到满足递归限制。我能想到的最好办法是让一个文件声明全局,然后调用下一个文件(一个完全重复的文件减去变量声明),然后递归调用它自己。下面是第一个的代码: # recurse.py def func(): global x x += 1 with open('recurse2.py', 'r') as f:

在无意中发现exec()之后,我一直在玩弄exec(),以便更好地理解它的工作原理。我试图让这个讨厌的脚本增加一个全局变量,读取自身,并用新的全局值调用exec,直到满足递归限制。我能想到的最好办法是让一个文件声明全局,然后调用下一个文件(一个完全重复的文件减去变量声明),然后递归调用它自己。下面是第一个的代码:

# recurse.py

def func():
    global x
    x += 1
    with open('recurse2.py', 'r') as f:    
        try:
            exec(f.read(), {'x': x})
        except RecursionError:
            print('maximum recursion depth reached at', x)

x = 0
func()
这是它执行的文件,它会自动执行:

# recurse2.py

def func():
    global x
    x += 1
    with open('recurse2.py', 'r') as f:    
        try:
            exec(f.read(), {'x': x})
        except RecursionError:
            print('maximum recursion depth reached at', x)

func()
只有一个文件可以达到相同的效果吗?

您可以这样做:

# recurse.py

def func():
    global x
    x += 1
    with open('recurse.py', 'r') as f:    
        try:
            exec(f.read(), {'x': x})
        except RuntimeError:
            print('maximum recursion depth reached at', x)

try:
    x
except NameError:
    x = 0
func()
您的初始示例的问题实际上并不特定于
exec
。只是程序本身在调用
func
之前将
x
设置为零。因此,传入起始值
x
无效:您正在执行的代码将设置一个新值
x
。在这个新版本中,try/except块测试名称是否已经存在,然后将其初始化为零

(我在这里使用RuntimeError是因为我没有引入RecursionError的Python 3.5,但它应该与RecursionError一样工作。)

您可以这样做:

# recurse.py

def func():
    global x
    x += 1
    with open('recurse.py', 'r') as f:    
        try:
            exec(f.read(), {'x': x})
        except RuntimeError:
            print('maximum recursion depth reached at', x)

try:
    x
except NameError:
    x = 0
func()
您的初始示例的问题实际上并不特定于
exec
。只是程序本身在调用
func
之前将
x
设置为零。因此,传入起始值
x
无效:您正在执行的代码将设置一个新值
x
。在这个新版本中,try/except块测试名称是否已经存在,然后将其初始化为零


(我在这里使用RuntimeError是因为我没有引入RecursionError的Python 3.5,但它在RecursionError中也应该起到同样的作用。)

是@BrenBarn的优秀解决方案的一个变体,由于打开的文件太多,它失败时会出现RuntimeError(@~500个递归),而不是IOError(@~256个递归):

#递归e.py

def func():
    global x
    x += 1
    with open('recurse.py') as source:
        string = source.read()
    try:
        exec(string, {'x': x})
    except RuntimeError:
        print('maximum recursion depth reached at', x)

try:
    x
except NameError:
    x = 0

func()

但是,您也可以根据需要扩展递归堆栈(
sys.setrecursionlimit()
)和/或打开文件限制(
ulimit-n
)。

是@BrenBarn优秀解决方案的一个变体,由于打开的文件太多,它会导致运行时错误(@~500次递归)而不是IOError(@~256次递归)失败:

#递归e.py

def func():
    global x
    x += 1
    with open('recurse.py') as source:
        string = source.read()
    try:
        exec(string, {'x': x})
    except RuntimeError:
        print('maximum recursion depth reached at', x)

try:
    x
except NameError:
    x = 0

func()

但是,您也可以根据需要扩展递归堆栈(
sys.setrecursionlimit()
)和/或打开文件限制(
ulimit-n
)。

在我的系统上,它不会因递归深度而失败,它会失败:OSError:[Errno 24]打开的文件太多:“recurse.py”(或Python 2中的IOError)--我意识到这对于每个系统都是不同的,但IOError是可以预防的。在我的系统上,它不会因为递归深度而失败,它会因为:OSError:[Errno 24]太多打开的文件而失败:“recurse.py”(或Python 2中的IOError)--我意识到这对于每个系统都是不同的,但IOError是可以预防的。啊,我没有注意到潜在的IOError问题,因为我在过去提高了打开文件的限制。说得好!啊,我没有注意到潜在的IOError问题,因为我在过去提高了打开文件的限制。说得好!