Функция 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')
).