When you define a class inside a function, every time the function is
run, you get a new class, which will compare unequal to any previous
versions (the same thing is true when you define a function within a
function by the way). You could cache the class instances, but to me,
it seems easier to just set the option in the __init__ method of the
class. Something like
class MaybeRealFunction(UndefinedFunction):
def __init__(self, *args, **kwargs):
self.real = kwargs.pop('real')
super(MaybeRealFunction, self).__init__(*args, **kwargs)
@staticmethod
def _eval_is_real(self):
return self.real
In [104]: r1 = MaybeRealFunction('f', real=False)
In [105]: r2 = MaybeRealFunction('f', real=False)
In [106]: r1(x) == r2(x)
Out[106]: True
In [107]: r1(x).is_real
Out[107]: False
But also note that:
In [108]: r3 = MaybeRealFunction('f', real=True)
In [109]: r2(x) == r3(x)
Out[109]: True
If real is the only assumption you care about, you should just create
two separate classes, RealFunction and NotRealFunction. Otherwise,
you'll need override _hashable_content so that the hash (and therein
equality) comes out different. You noted that you are using them as
keys in dictionaries, so probably you do care about this.
By the way, it would be nice if Function supported this directly,
i.e., Function('f', real=False). If you don't mind actually digging
into the metaclasses, a pull request would nice.
Aaron Meurer
On Tue, Jan 28, 2014 at 10:16 AM, Björn Dahlgren <[email protected]> wrote:
> Hello!
>
> I have an application where I use undefined functions as keys in
> dictionaries.
>
> This works great out of the box for sympy.Function
> However, I want to set real=True so I created a class factory which
> overrides _eval_is_real
>
> Now the trouble starts. I tried to work my way through the jungle of
> metaclasses and the assumptions systems
> but I don't seem to be able to fix this:
>
> -*- coding: utf-8 -*-
>
> from sympy.core.function import UndefinedFunction
> import sympy
>
> def MaybeRealFunction(key, real=None):
>
> class _Function(UndefinedFunction):
> @staticmethod
> def _eval_is_real(self):
> return real
>
> return _Function(key)
>
>
> def main():
> x = sympy.Symbol('x')
> assert x == sympy.Symbol('x')
>
> f_x = sympy.Function('f')(x)
> assert f_x == sympy.Function('f')(x)
>
> g_x = MaybeRealFunction('g', real=True)(x)
> assert g_x.is_real
> assert g_x == g_x
> assert g_x == MaybeRealFunction('g', real=True)(x) # <--- This one fails
>
> if __name__ == '__main__':
> main()
>
>
> Any ideas?
>
> Best regards,
> /Björn
>
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sympy.
> For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy.
For more options, visit https://groups.google.com/groups/opt_out.