使用 setattr() 将字符串转换为变量
Using setattr() to convert strings to variables
我正在创建一个 sigsum() 函数,它使用输入方程和输入变量求和。这是我目前所拥有的:
def sigsum(eqn, index, lower=0, upper=None, step=1):
if type(step) is not int:
raise TypeError('step must be an integer')
elif step < 1:
raise ValueError('step must be greater than or equal to 1')
if upper is None:
upper = 1280000
if lower is None:
lower = -1280000
if (upper - lower) % step:
upper -= (upper - lower) % step
index = lower
total = 0
while True:
total += eqn
if index == upper:
break
index += step
return total
函数的使用:
print(sigsum('1/(i+5)','i'))
>>> 12.5563
我当前的问题是将 'eqn' 和 'index' 转换为存在于函数局部命名空间内的变量。我听说使用 exec 不是一个好主意,也许 setattr() 可能会起作用。谁能帮我吗?
谢谢
对于 eqn
我建议使用 lambda 函数:
eqn = lambda i: 1 / (i + 5)
那么不需要index
,因为它只是"the variable passed to the function"(不需要名字)。
那么你的函数就变成了
def integrate(fn, start = 0, end = 128000, step = 1):
"""
Return a stepwise approximation of
the integral of fn from start to end
"""
num_steps = (end - start) // step
if num_steps < 0:
raise ValueError("bad step value")
else:
return sum(fn(start + k*step) for k in range(num_steps))
你可以运行喜欢
res = step_integrate(eqn) # => 10.253703030104417
请注意,这有很多步骤,其中许多涉及非常小的数字;舍入误差可能成为一个主要问题。如果精度很重要,您可能需要手动推导积分,
from math import log
eqn = lambda i: 1 / (i + 5)
eqn.integral = lambda i: log(i + 5)
def integrate(fn, start = 0, end = 128000, step = 1):
"""
Return the integral of fn from start to end
If fn.integral is defined, used it;
otherwise do a stepwise approximation
"""
if hasattr(fn, "integral"):
return fn.integral(end) - fn.integral(start)
else:
num_steps = (end - start) // step
if num_steps < 0:
raise ValueError("bad step value")
else:
return sum(fn(start + k*step) for k in range(num_steps))
这又是运行像
res = step_integrate(eqn) # => 10.150386692204735
(请注意,逐步逼近大约高出 1%。)
我会按照 Hugh Bothwell 的建议使用 lambda 函数
将不得不修改 sigsum 如下
def sigsum(eqn, lower=0, upper=None, step=1):
if type(step) is not int:
raise TypeError('step must be an integer')
elif step < 1:
raise ValueError('step must be greater than or equal to 1')
if upper is None:
upper = 1280000
if lower is None:
lower = -1280000
if (upper - lower) % step:
upper -= (upper - lower) % step
index = lower
total = 0
while True:
total += eqn(index)
if index == upper:
break
index += step
return total
函数的使用:
print(sigsum(lambda i: 1/(i+5)))
>>> 12.5563
你也可以单独定义一个函数:
def myfunction(i):
return 1/(i+5)
并将其传递给 sigsum
print(sigsum(myfunction))
>>> 12.5563
能够将函数作为参数传递在计算机语言语音函数中作为第一个 class 对象调用。 (例如 C 和 java 没有,javascript 和 python 有)
我正在创建一个 sigsum() 函数,它使用输入方程和输入变量求和。这是我目前所拥有的:
def sigsum(eqn, index, lower=0, upper=None, step=1):
if type(step) is not int:
raise TypeError('step must be an integer')
elif step < 1:
raise ValueError('step must be greater than or equal to 1')
if upper is None:
upper = 1280000
if lower is None:
lower = -1280000
if (upper - lower) % step:
upper -= (upper - lower) % step
index = lower
total = 0
while True:
total += eqn
if index == upper:
break
index += step
return total
函数的使用:
print(sigsum('1/(i+5)','i'))
>>> 12.5563
我当前的问题是将 'eqn' 和 'index' 转换为存在于函数局部命名空间内的变量。我听说使用 exec 不是一个好主意,也许 setattr() 可能会起作用。谁能帮我吗? 谢谢
对于 eqn
我建议使用 lambda 函数:
eqn = lambda i: 1 / (i + 5)
那么不需要index
,因为它只是"the variable passed to the function"(不需要名字)。
那么你的函数就变成了
def integrate(fn, start = 0, end = 128000, step = 1):
"""
Return a stepwise approximation of
the integral of fn from start to end
"""
num_steps = (end - start) // step
if num_steps < 0:
raise ValueError("bad step value")
else:
return sum(fn(start + k*step) for k in range(num_steps))
你可以运行喜欢
res = step_integrate(eqn) # => 10.253703030104417
请注意,这有很多步骤,其中许多涉及非常小的数字;舍入误差可能成为一个主要问题。如果精度很重要,您可能需要手动推导积分,
from math import log
eqn = lambda i: 1 / (i + 5)
eqn.integral = lambda i: log(i + 5)
def integrate(fn, start = 0, end = 128000, step = 1):
"""
Return the integral of fn from start to end
If fn.integral is defined, used it;
otherwise do a stepwise approximation
"""
if hasattr(fn, "integral"):
return fn.integral(end) - fn.integral(start)
else:
num_steps = (end - start) // step
if num_steps < 0:
raise ValueError("bad step value")
else:
return sum(fn(start + k*step) for k in range(num_steps))
这又是运行像
res = step_integrate(eqn) # => 10.150386692204735
(请注意,逐步逼近大约高出 1%。)
我会按照 Hugh Bothwell 的建议使用 lambda 函数 将不得不修改 sigsum 如下
def sigsum(eqn, lower=0, upper=None, step=1):
if type(step) is not int:
raise TypeError('step must be an integer')
elif step < 1:
raise ValueError('step must be greater than or equal to 1')
if upper is None:
upper = 1280000
if lower is None:
lower = -1280000
if (upper - lower) % step:
upper -= (upper - lower) % step
index = lower
total = 0
while True:
total += eqn(index)
if index == upper:
break
index += step
return total
函数的使用:
print(sigsum(lambda i: 1/(i+5)))
>>> 12.5563
你也可以单独定义一个函数:
def myfunction(i):
return 1/(i+5)
并将其传递给 sigsum
print(sigsum(myfunction))
>>> 12.5563
能够将函数作为参数传递在计算机语言语音函数中作为第一个 class 对象调用。 (例如 C 和 java 没有,javascript 和 python 有)