неподдерживаемые операнды для 'function' и 'int', лямбды убивают меня - PullRequest
0 голосов
/ 20 января 2019

Я программирую производный калькулятор, и как часть этого я должен быть в состоянии создавать представления функционала, а затем иметь возможность заменять переменные числами и затем выполнять математику.я пытаюсь использовать лямбды, чтобы сделать это для меня, но я продолжаю получать ошибку 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 голосов
/ 20 января 2019

Функция doit возвращает другую функцию.Когда вы пишете doit(fext) + x.get_val(), вы пытаетесь добавить эту функцию к чему-то еще (целому числу, как оказалось), которое не может работать.

Мне не совсем понятно, в чем смыслdoit есть.Кажется, он пытается оценить экспоненциальное выражение, но на самом деле это не имеет никакого смысла, поэтому я не могу исправить это для вас.

То, что я думаю, вы хотите,уметь оценивать любое данное выражение и уметь преобразовывать выражение в его производную.Я думаю, что возиться с лямбдами и другими подобными вещами - неправильный способ сделать это.Вместо этого вам нужна более общая иерархия типов 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 - это int (не Constant, поскольку нам никогда не нужно eval)).Он не поддерживает степени произвольных выражений для произвольных выражений (которые могут иметь очень сложные производные).Другие операции, такие как вычитание и деление, не слишком сложны, я просто опустил их, чтобы сократить код.Вы могли бы также сделать проверку операций __add__ и __mul__ для int (или, возможно, float) аргументов и автоматически связать их в Constant s для вас.Тогда вы могли бы написать действительно хорошие выражения, такие как f = x**3 + x**2 * 4 + x * -1 + 8, и это просто сработало бы (учитывая x = Variable('x')).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...