我让Decorators跟踪了一些递归函数。我想知道返回try块的方法。我已经尝试了while循环,但它对我不起作用,因为我的函数是递归的,任何人都可以告诉我如何处理它? 问题是当函数change_t引发异常时,我想继续执行我的 尝试阻止
这是我的装饰者和功能
正确的结果:
,- change_t([9, 7, 5], 44)
| ,- change_t([9, 7, 5], 35)
| | ,- change_t([9, 7, 5], 26)
| | | ,- change_t([9, 7, 5], 17)
| | | | ,- change_t([9, 7, 5], 8)
| | | | | ,- change_t([7, 5], 8)
| | | | | | ,- change_t([7, 5], 1)
| | | | | | | ,- change_t([5], 1)
| | | | | | | | ,- change_t([], 1)
| | | | | | ,- change_t([5], 8)
| | | | | | | ,- change_t([5], 3)
| | | | | | | | ,- change_t([], 3)
| | | | | | | ,- change_t([], 8)
| | | | ,- change_t([7, 5], 17)
| | | | | ,- change_t([7, 5], 10)
| | | | | | ,- change_t([7, 5], 3)
| | | | | | | ,- change_t([5], 3)
| | | | | | | | ,- change_t([], 3)
| | | | | | ,- change_t([5], 10)
| | | | | | | ,- change_t([5], 5)
| | | | | | | | ,- change_t([5], 0)
| | | | | | | | `- []
| | | | | | | `- [5]
| | | | | | `- [5, 5]
| | | | | `- [5, 5]
| | | | `- [7, 5, 5]
| | | `- [7, 5, 5]
| | `- [9, 7, 5, 5]
| `- [9, 9, 7, 5, 5]
`- [9, 9, 9, 7, 5, 5]
这是我得到的: 它在我预期异常后立即停止
change_t([9, 7, 5], 44)
,- change_t ([9, 7, 5], 44)
| ,- change_t ([9, 7, 5], 35)
| | ,- change_t ([9, 7, 5], 26)
| | | ,- change_t ([9, 7, 5], 17)
| | | | ,- change_t ([9, 7, 5], 8)
| | | | | ,- change_t ([7, 5], 8)
| | | | | | ,- change_t ([7, 5], 1)
| | | | | | | ,- change_t ([5], 1)
| | | | | | | | ,- change_t ([], 1)
| | | | | | `- 1
| | | | | `- 1
| | | | `- 1
| `- 8
`- 8
`- 17
`- 26
`- 35
`- 44
44
答案 0 :(得分:2)
正如我在评论中所说,你需要重新加载异常,以便原始函数可以实际捕获它并继续。你想在except处理程序中只减少一个缩进,这样你就不会在左边太远了:
class traced(object):
indent =0
def __init__(self,f):
self.__name__=f.__name__
self.indent=0
self.f=f
def __call__(self,*args,**kwargs):
string=""
if kwargs:
l=[]
for (key, value) in kwargs.items():
l.append(str(key) + "=" + str(value))
a=', '.join(l)
string = '('+a+')'
else:
l=[]
for value in args:
l.append(str(value))
a=', '.join(l)
string = '('+a+')'
print('| ' * traced.indent + ',- '+ self.__name__+' '+string)
try:
traced.indent+=1
value = self.f(*args,**kwargs)
except Exception:
traced.indent-=1 # <-- only decrement by one
raise # <-- reraise the exception so the original function can catch it
traced.indent-=1
print('| '* traced.indent + "`- "+ repr(value))
return value
然后它起作用:
>>> change_t([9, 7, 5], 44)
,- change_t ([9, 7, 5], 44)
| ,- change_t ([9, 7, 5], 35)
| | ,- change_t ([9, 7, 5], 26)
| | | ,- change_t ([9, 7, 5], 17)
| | | | ,- change_t ([9, 7, 5], 8)
| | | | | ,- change_t ([7, 5], 8)
| | | | | | ,- change_t ([7, 5], 1)
| | | | | | | ,- change_t ([5], 1)
| | | | | | | | ,- change_t ([], 1)
| | | | | | ,- change_t ([5], 8)
| | | | | | | ,- change_t ([5], 3)
| | | | | | | | ,- change_t ([], 3)
| | | | | | | ,- change_t ([], 8)
| | | | ,- change_t ([7, 5], 17)
| | | | | ,- change_t ([7, 5], 10)
| | | | | | ,- change_t ([7, 5], 3)
| | | | | | | ,- change_t ([5], 3)
| | | | | | | | ,- change_t ([], 3)
| | | | | | ,- change_t ([5], 10)
| | | | | | | ,- change_t ([5], 5)
| | | | | | | | ,- change_t ([5], 0)
| | | | | | | | `- []
| | | | | | | `- [5]
| | | | | | `- [5, 5]
| | | | | `- [5, 5]
| | | | `- [7, 5, 5]
| | | `- [7, 5, 5]
| | `- [9, 7, 5, 5]
| `- [9, 9, 7, 5, 5]
`- [9, 9, 9, 7, 5, 5]
[9, 9, 9, 7, 5, 5]
最后我会清理装饰器,使其更简洁明了你在做什么:
class traced(object):
indent = 0
def __init__(self, f):
self.__name__ = f.__name__
self.f = f
def __call__(self, *args, **kwargs):
if kwargs:
l = [str(key) + '=' + str(value) for key, value in kwargs.items()]
else:
l = list(map(str, args))
print('| ' * traced.indent + ',- {0} ({1})'.format(self.__name__, ', '.join(l)))
try:
traced.indent += 1
value = self.f(*args,**kwargs)
finally:
traced.indent -= 1
print('| ' * traced.indent + '`- ' + repr(value))
return value
这里我简化了整个参数聚合以使用列表理解。我还使用字符串格式化使格式更清晰。这样你就可以把你必须放在列表内容周围的括号组合起来(你在两种情况下都做了btw。)。当你在没有真正查看它的情况下重新加载异常时,我们不需要先捕获它,而只是确保我们调整finally块中的缩进。
实际上,为什么要检查 变量参数或关键字参数?只需接受两者:
l = list(map(str, args))
l.extend([str(key) + '=' + str(value) for key, value in kwargs.items()])
答案 1 :(得分:0)
当引发异常时,将从引发它的代码中放弃控制权。而是将其移交给捕获该异常的第一个catch块,或者移交给主解释器循环。
看看你的代码:
if a==0:
return []
elif len(l)==0:
raise ChangeException()
elif l[0]>a:
return change_t(l[1:],a)
当第三个条件为真时会发生什么,即l[0]>a
,当l的长度为1时?然后在下一个调用中,即return change_t(l[1:],a)
,它将引发一个除主循环之外的任何人都不会捕获的异常:这就是你的代码失败的原因。您需要在try catch子句中包含第三个条件,具体取决于您想要实现的目标。