Python number-like class that remembers arithmetic operations?

前端 未结 5 595
甜味超标
甜味超标 2020-12-05 05:46

I\'m wondering if there exists a python module that would allow me to do something like this:

x = MagicNumber()
x.value = 3
y = 2 * (x + 2) ** 2 - 8
print y          


        
相关标签:
5条回答
  • 2020-12-05 06:18

    Isn't this called a function? This may sound like a simple answer, but I mean it sincerely.

    def y(x):
        return 2 * (x + 2) ** 2 - 8
    

    Aren't you thinking in the wrong direction with this one?

    To address the clarification:

    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
    

    I guess I'm more in favor of this type of a solution, although I see the benefit in the sympy module. Preference, I guess.

    0 讨论(0)
  • 2020-12-05 06:20

    Something like this?

    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)
    

    And here it is in action:

    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)]
    
    0 讨论(0)
  • 2020-12-05 06:28
    >>> 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
    
    0 讨论(0)
  • 2020-12-05 06:41

    I think the difficulty is in "how to keep operators priority" rather than implementing a class.

    I suggest to look at a different notation (like Reverse Polish Notation) that may help in getting rid of priority issues...

    0 讨论(0)
  • 2020-12-05 06:42

    You could give sympy, a computer algebra system written in Python, give a try.

    E.g.

    >>> from sympy import Symbol
    >>> x = Symbol('x')
    >>> y = 2 * (x + 2) ** 2 - 8
    >>> y
    2*(x + 2)**2 - 8
    >>> y.subs(x,3)
    42
    >>> y.subs(x,2)
    24
    
    0 讨论(0)
提交回复
热议问题