类似Python数字的类,能够记住算术运算?
我想知道是否存在允许我执行以下操作的python模块:类似Python数字的类,能够记住算术运算?,python,Python,我想知道是否存在允许我执行以下操作的python模块: x = MagicNumber() x.value = 3 y = 2 * (x + 2) ** 2 - 8 print y # 42 x.value = 2 print y # 24 因此,MagicNumber将实现所有特殊的操作符方法,它们将返回MagicNumber的实例,同时跟踪执行的操作。有这样的课吗 编辑:澄清 我想在一个模块中使用它,该模块应该记住用户希望执行的一些任意计算的许多参数。因此,用户将设置参数,然后使用
x = MagicNumber()
x.value = 3
y = 2 * (x + 2) ** 2 - 8
print y # 42
x.value = 2
print y # 24
因此,MagicNumber
将实现所有特殊的操作符方法,它们将返回MagicNumber的实例,同时跟踪执行的操作。有这样的课吗
编辑:澄清
我想在一个模块中使用它,该模块应该记住用户希望执行的一些任意计算的许多参数。因此,用户将设置参数,然后使用它们生成结果。然后,如果他决定改变一个参数,这个改变会立即反映在他的结果中。因此,只有一个参数实例的非常简化的使用会话如下所示:
p = MyParams()
p.distance = 13.4 # I use __getattr__ and __setattr__ such that
p.speed = 3.14 # __getattr__ returns MagicNumber instances
time = p.distance / p.speed
编辑2:更多澄清
好吧,我会做我从一开始就应该做的事。我将提供上下文
你是一名工程师,你将制作一份LaTeX文档,详细说明一些原型小工具的工作原理和属性。这是一项针对不同原型重复执行的任务。您可以编写一个小型的LaTeX python接口。对于每个原型,您创建一个python模块,该模块生成必要的文档。在其中,您可以键入LaTeX代码,同时根据需要计算变量,以便在上下文中进行计算。一段时间后,您会注意到两个问题:
这不是叫
函数吗?这听起来可能是一个简单的答案,但我是真心的
def y(x):
return 2 * (x + 2) ** 2 - 8
你是不是想错了方向了
为解决澄清问题:
class MyParams():
distance = 0.0
speed = 0.0
def __call__(self):
return self.distance / self.speed
p = MyParams()
p.distance = 13.4 # These are properties
p.speed = 3.14 # where __get__ returns MagicNumber instances
time = p() # 4.26
p.speed = 2.28
time = p() # 5.88
我想我更赞成这种类型的解决方案,尽管我看到sympy模块的好处。首选项,我猜。我认为困难在于“如何保持运算符优先级”,而不是实现类
>>> magic = lambda x: eval('2 * (x + 2) ** 2 - 8')
>>> magic(2)
24
>>> magic(3)
42
>>> magic = lambda x: eval('x ** 4')
>>> magic(2)
16
>>> magic(3)
81
我建议看一个不同的符号(如),它可能有助于消除优先问题…类似的东西
import operator
MAKE_BINARY = lambda opfn : lambda self,other : BinaryOp(self, asMagicNumber(other), opfn)
MAKE_RBINARY = lambda opfn : lambda self,other : BinaryOp(asMagicNumber(other), self, opfn)
class MagicNumber(object):
__add__ = MAKE_BINARY(operator.add)
__sub__ = MAKE_BINARY(operator.sub)
__mul__ = MAKE_BINARY(operator.mul)
__radd__ = MAKE_RBINARY(operator.add)
__rsub__ = MAKE_RBINARY(operator.sub)
__rmul__ = MAKE_RBINARY(operator.mul)
# __div__ = MAKE_BINARY(operator.div)
# __rdiv__ = MAKE_RBINARY(operator.div)
__truediv__ = MAKE_BINARY(operator.truediv)
__rtruediv__ = MAKE_RBINARY(operator.truediv)
__floordiv__ = MAKE_BINARY(operator.floordiv)
__rfloordiv__ = MAKE_RBINARY(operator.floordiv)
def __neg__(self, other):
return UnaryOp(self, lambda x : -x)
@property
def value(self):
return self.eval()
class Constant(MagicNumber):
def __init__(self, value):
self.value_ = value
def eval(self):
return self.value_
class Parameter(Constant):
def __init__(self):
super(Parameter, self).__init__(0.0)
def setValue(self, v):
self.value_ = v
value = property(fset=setValue, fget=lambda self: self.value_)
class BinaryOp(MagicNumber):
def __init__(self, op1, op2, operation):
self.op1 = op1
self.op2 = op2
self.opn = operation
def eval(self):
return self.opn(self.op1.eval(), self.op2.eval())
class UnaryOp(MagicNumber):
def __init__(self, op1, operation):
self.op1 = op1
self.operation = operation
def eval(self):
return self.opn(self.op1.eval())
asMagicNumber = lambda x : x if isinstance(x, MagicNumber) else Constant(x)
这就是行动:
x = Parameter()
# integer division
y = 2*x*x + 3*x - x//2
# or floating division
# y = 2*x*x + 3*x - x/2
x.value = 10
print(y.value)
# prints 225
x.value = 20
print(y.value)
# prints 850
# compute a series of x-y values for the function
print([(x.value, y.value) for x.value in range(5)])
# prints [(0, 0), (1, 5), (2, 13), (3, 26), (4, 42)]
我事先不知道将执行哪些算术运算,而且我可能不会假设它们是一次性完成的,或者是在同一个地方完成的。也许用一些预期的用例更新您的问题是个好主意。您将如何准确地构造这些操作,以及为什么不想将字符(例如,*
)映射到函数(例如,乘法
)?Re:update。你又把我关在一个特别的问题上。我不知道我的模块的用户希望做什么样的参数或问题。他应该可以自由地自己命名参数,并在他认为合适的时候使用它们,并且可以像计算正常值一样使用它们。我只是想给他额外的追溯性修改的能力。等等,最终用户会输入你在问题的第一个代码块中输入的代码吗?在这种情况下,您可以在eval
命令中结束调用,在执行时替换变量:例如eval('2*(x+2)**2-8'.replace('x',str(3))
--3
是x
参数的当前值?好的,欢迎背景。从我对你的问题的设想来看,我仍然支持这个解决方案;可能是因为我不认为创建一个包含一些定义在其中的变量的类,以及一个可以清晰地注释和描述的计算函数有什么问题。我将保留我的答案,并建议您选择最符合您个人偏好的解决方案(我认为这可以归结为)。不要轻描淡写您的答案,而是出于好奇:与使用函数相比,这种构造有什么好处?我看起来不太清晰,你仍然需要用代码来构建它。。。在这种情况下,我真的对库的附加值很感兴趣。@jro:OP实际上要求提供一个代数库,这是一个(除其他外)处理代数的库。在函数上,这将允许求解或表达多个符号的方程,其中替换值包括符号。这与我的想法最接近,因为我可以通过几个步骤构建表达式。但是,使用此方法时,我需要调用一个特殊函数对其进行求值——我希望它是无缝的,并且从一开始就给x
一个值。但也许我可以将Symbol
子类化,这样做的工作量就会少很多。谢谢@eumiro,他事先不知道将执行哪些算术运算。我认为Python解释器将处理优先级问题-他不想解析表达式,他想将解析后的表达式捕获为可计算的(这是一个单词吗?)对象。有这样的类吗?保罗:“现在有了!”。我希望我有更多的选票。我站在一个巨人的肩膀上,呃,巨蟒?(蟒蛇有肩膀吗?)!对于符号代数,它还有一些缺点,但这不是批评。您必须注意分配给x.value
:使用整数会得到意外的结果。还有一些符号操作也不错:在上面的例子中,-y
是什么@保尔·麦奎尔:我会把这当作一个练习,因为我最近在一个类似的方向上进行实验,但我没有得出任何像你一样简洁的结论。如果用整数“你得到了意想不到的结果”,也许你指的是整数除法带来的惊喜。如果您想强制所有expr
x = Parameter()
# integer division
y = 2*x*x + 3*x - x//2
# or floating division
# y = 2*x*x + 3*x - x/2
x.value = 10
print(y.value)
# prints 225
x.value = 20
print(y.value)
# prints 850
# compute a series of x-y values for the function
print([(x.value, y.value) for x.value in range(5)])
# prints [(0, 0), (1, 5), (2, 13), (3, 26), (4, 42)]