_NQuad 的集成函数中没有赋值的情况下如何更新 args?有人可以解释一下这段代码发生了什么吗?
from scipy.integrate import quad
from functools import partial
class _RangeFunc:
def __init__(self, range_):
self.range_ = range_
def __call__(self, *args):
"""Return stored value.
*args needed because range_ can be float or func, and is called with
variable number of parameters.
"""
return self.range_
class _OptFunc:
def __init__(self, opt):
self.opt = opt
def __call__(self, *args):
"""Return stored dict."""
return self.opt
class _NQuad:
def __init__(self, func, ranges, opts, full_output):
self.loop = 0
self.abserr = 0
self.func = func
self.ranges = ranges
self.opts = opts
self.maxdepth = len(ranges)
self.full_output = full_output
if self.full_output:
self.out_dict = {'neval': 0}
def integrate(self, *args, **kwargs):
depth = kwargs.pop('depth', 0)
if kwargs:
raise ValueError('unexpected kwargs')
# Get the integration range and options for this depth.
ind = -(depth + 1)
fn_range = self.ranges[ind]
low, high = fn_range(*args)
fn_opt = self.opts[ind]
opt = dict(fn_opt(*args))
if 'points' in opt:
opt['points'] = [x for x in opt['points'] if low <= x <= high]
if depth + 1 == self.maxdepth:
f = self.func
else:
f = partial(self.integrate, depth=depth+1)
quad_r = quad(f, low, high, args=args, full_output=self.full_output,**opt)
print(f'loop: {self.loop}; args: {args}; quad_r: {quad_r}')
self.loop += 1
value = quad_r[0]
abserr = quad_r[1]
if self.full_output:
infodict = quad_r[2]
# The 'neval' parameter in full_output returns the total
# number of times the integrand function was evaluated.
# Therefore, only the innermost integration loop counts.
if depth + 1 == self.maxdepth:
self.out_dict['neval'] += infodict['neval']
self.abserr = max(self.abserr, abserr)
if depth > 0:
return value
else:
# Final result of N-D integration with error
if self.full_output:
return value, self.abserr, self.out_dict
else:
return value, self.abserr
def nquad(func, ranges, args=None, opts=None, full_output=False):
depth = len(ranges)
ranges = [rng if callable(rng) else _RangeFunc(rng) for rng in ranges]
if args is None:
args = ()
if opts is None:
opts = [dict([])] * depth
if isinstance(opts, dict):
opts = [_OptFunc(opts)] * depth
else:
opts = [opt if callable(opt) else _OptFunc(opt) for opt in opts]
return _NQuad(func, ranges, opts, full_output).integrate(*args)
def func(x, y):
return x*y**2
ranges = [[0, 2], [0, 1]]
opts = {"epsabs": 1.49e-8, "epsrel": 1.49e-8}
args = ()
full_output = False
result = nquad(func=func, ranges=ranges, args=args, opts=opts, full_output=False)
result
_NQuad 的Integrate 方法中的args 参数是一个可变长度的参数列表,它以args=args 的形式传递给quad 函数。在 _NQuad 的每个循环中,使用 *args 语法将 args 元组解包为单独的参数,然后将其用于各种计算。
因此,虽然在集成方法中没有对 args 进行显式赋值,但随着解压参数的值发生变化,args 的内容会随着循环的每次迭代而有效地更新。
总之,args 参数根据需要进行传递和解包,并且通过对解包参数的操作隐式更新其内容。
这是一个修改其
args
参数的简单函数示例。它没有做任何重要的事情,但显示了如何更改该参数。每次调用该函数时都会发生变化,但除此之外 quad
不会对其执行任何操作。
In [222]: from scipy.integrate import quad
In [223]: def fun(x,*args):
...: args[0].append('foobar')
...: return x**2
...:
In [224]: alist=[]; quad(fun, 0, 1, args=(alist,))
Out[224]: (0.33333333333333337, 3.700743415417189e-15)
In [225]: alist
Out[225]:
['foobar',
'foobar',
'foobar',
'foobar',
'foobar',
'foobar',
'foobar',
...
'foobar']