【问题标题】:unsupported operands for 'function' and 'int', lambdas are killing me'function' 和 'int' 不支持的操作数,lambdas 正在杀死我
【发布时间】:2019-01-20 06:27:38
【问题描述】:

我正在编写一个导数计算器,作为其中的一部分,我必须能够创建函数表示,然后能够用数字替换变量,然后进行数学运算。我试图使用 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'

【问题讨论】:

  • 请附上make_pwr和make_const的代码
  • 请显示回溯。错误发生在哪里?
  • 如果我猜不到,你不会在某个地方调用 lambda。
  • 读取错误:你正在尝试添加一个函数(doit的返回值)和一个整数。
  • 如果您是 Python 新手,这看起来是一件非常复杂的事情。您的代码中有大量非pythonic 的东西可能会让您更难理解出了什么问题(并且让我们更难理解您打算做什么)。例如,您不恰当地为自己的变量使用 __dunder__ 名称(可能应该只使用简单的 self.value 名称)并且 not 使用定义明确的 dunder 方法,例如 __add__ 和 @987654332 @.

标签: python math int


【解决方案1】:

doit 函数返回另一个函数。当您编写doit(fext) + x.get_val() 时,您正试图将该函数添加到其他东西(结果是一个整数),这不可能工作。

我不太清楚doit 的意义是什么。它似乎试图评估一个指数表达式,但它并没有任何意义,所以我无法真正为你解决它。

我认为你想要的是能够评估任何给定的表达式,并且能够将表达式转换为它的导数。我认为搞乱 lambdas 和其他类似的东西是错误的做法。相反,您需要更通用的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 形式的幂(其中x 是Variable,c 是@ 987654334@(不是Constant,因为我们永远不需要eval它))。它不支持任意表达式对任意表达式的幂(可能有非常复杂的导数)。减法和除法等其他操作并不难,我只是省略了它们以缩短代码。您可能还可以让__add__ 和__mul__ 操作检查int(或者可能是float)参数,并为您自动将它们捆绑到Constants 中。然后你可以写出非常好的表达式,比如f = x**3 + x**2 * 4 + x * -1 + 8,它就可以工作(给定x = Variable('x'))。

【讨论】:

  • 感谢大家抽出宝贵时间来做这件事!老实说,我很惊讶有人花时间和精力来帮助我解决我的问题。非常感谢!
猜你喜欢
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2015-01-17
相关资源
最近更新 更多