不支持“函数”和“整数”的操作数,lambda杀死了我

时间:2019-01-20 06:27:39

标签: python math int

我正在编程一个导数计算器,因此,我必须能够创建函数表示,然后能够用数字替换变量,然后进行数学运算。我正在尝试使用lambdas为我执行此操作,但我不断收到错误TypeError: unsupported operand type(s) for -: 'function' and 'int'

def doit(p):
    a = p.get_base()
    b = p.get_deg()
    return lambda x: a ** b.get_val()

if __name__ == '__main__':

    fext = make_pwr('x', 5)
    f = lambda x: doit(fext) + x.get_val()

    print(f(make_const(5)))

这是const类的样子:

#!/usr/bin/python

class const(object):
    def __init__(self, val=0.0):
        self.__val__ = val

    def get_val(self):
        return self.__val__

    def __str__(self):
        return str(self.__val__)

    @staticmethod
    def add(c1, c2):
        assert isinstance(c1, const)
        assert isinstance(c2, const)
        v1, v2 = c1.get_val(), c2.get_val()
        return const(val=(v1 + v2))

    @staticmethod
    def mult(c1, c2):
        assert isinstance(c1, const)
        assert isinstance(c2, const)
        v1, v2 = c1.get_val(), c2.get_val()
        return const(val=(v1 * v2))

    @staticmethod
    def divide(c1, c2):
        assert isinstance(c1, const)
        assert isinstance(c2, const)
        v1, v2 = c1.get_val(), c2.get_val()
        return const(val=(v1 / v2))

和功率等级:

#!/usr/bin/python

from const import const
class pwr(object):
    def __init__(self, base=None, deg=None):
        self.__base__ = base
        self.__deg__  = deg

    def get_base(self):
        return self.__base__

    def get_deg(self):
        return self.__deg__

    def __str__(self):
        return '(' + str(self.__base__) + '^' + str(self.__deg__) + ')'

这是回溯:

Traceback (most recent call last):
  File "D:/Shared/OneDrive/skewl/Spring 2019/CS 3430/hw01/maker.py", line 39, in <module>
    print(f(make_const(5)))
  File "D:/Shared/OneDrive/skewl/Spring 2019/CS 3430/hw01/maker.py", line 37, in <lambda>
    f = lambda x: doit(fext) + x.get_val()
TypeError: unsupported operand type(s) for +: 'function' and 'int'

1 个答案:

答案 0 :(得分:2)

doit函数返回另一个函数。当您编写doit(fext) + x.get_val()时,您试图将该功能添加到其他功能(实际上是一个整数)上。

我不清楚doit的含义是什么。它似乎正在尝试评估一个指数表达式,但是它实际上没有任何意义,因此我无法为您真正解决它。

认为想要的是能够评估任何给定的表达式,并能够将表达式转换为其派生。我认为弄乱lambda和类似的东西是错误的方式。相反,您需要一个更通用的Expression类型层次结构。像这样:

from abc import ABCMeta, abstractmethod

class Expression(metaclass=ABCMeta):
    @abstractmethod
    def eval(self, **kwargs):
        pass

    @abstractmethod
    def derivative(self, var):
        pass

    def __add__(self, other):
        return Sum(self, other)

    def __mul__(self, other):
        return Product(self, other)

class Constant(Expression):
    def __init__(self, value):
        self.value = value

    def eval(self, **kwargs):
        return self.value

    def derivative(self, var):
        return Constant(0)

class Variable(Expression):
    def __init__(self, name):
        self.name = name

    def eval(self, **kwargs):
        return kwargs[self.name]   # TODO: raise a better exception if the name is not found

    def derivative(self, var):
        if self.name == var:
            return Constant(1)
        return Constant(0)

    def __pow__(self, exponent):
        return SimplePower(self, exponent)

class Sum(Expression):
    def __init__(self, lhs, rhs):
        self.lhs = lhs
        self.rhs = rhs

    def eval(self, **kwargs):
        return self.lhs.eval(**kwargs) + self.rhs.eval(**kwargs)

    def derivative(self, var):
        return self.lhs.derivative(var) + self.rhs.derivative(var)

class Product(Expression):
    def __init__(self, lhs, rhs):
        self.lhs = lhs
        self.rhs = rhs

    def eval(self, **kwargs):
        return self.lhs.eval(**kwargs) * self.rhs.eval(**kwargs)

    def derivative(self, var):
        return self.lhs.derivative(var) * self.rhs + self.rhs.derivative(var) * self.lhs

class SimplePower(Expression):
    def __init__(self, var, exponent):
        self.var = var
        self.exponent = exponent

    def eval(self, **kwargs):
        return self.var.eval(**kwargs) ** self.exponent

    def derivative(self, var):
        if var == self.var.name:
            return Constant(self.exponent) * SimplePower(self.var, self.exponent-1)
        else:
            return Constant(0)

这是它的使用演示:

>>> x = Variable('x')
>>> f = x ** 2 + x * Constant(3) + Constant(-2)  # f(x) = x^2 + 3x - 2
>>> f.eval(x=1)
2
>>> f.eval(x=2)
8
>>> f.eval(x=3)
16
>>> f_prime = f.derivative('x')  # f'(x) = 2x + 3
>>> f_prime.eval(x=0)
3
>>> f_prime.eval(x=1)
5
>>> f_prime.eval(x=2)
7

请注意,因为__pow__仅在Variable中定义,而不是在Expression中定义,所以此代码仅支持x**c形式的幂(其中xVariablecint(不是Constant,因为我们不需要eval)。它不支持任意表达式对任意表达式(可能具有非常复杂的派生)的功能。减法和除法等其他操作也不太难,我只是省略了它们以缩短代码。您可能还可以使__add____mul__操作检查int(或者也许是float)自变量,并自动将它们捆绑到Constant中。然后,您可以编写像f = x**3 + x**2 * 4 + x * -1 + 8这样的非常好的表达式,它就可以工作(给定x = Variable('x'))。