For most classes there isn't, but there can be. Using func instead of
type() allows objects to have a function that isn't its literal Python
class. This is necessary, for instance, if you want to allow the
function to also be usable as an expression, since in that case it
would also have to be a Python object (not a class).
An example of this are the predicate objects, like Q.positive. We want
to be able to use both Q.positive and Q.positive(x) in logic
expressions. If Q.positive were the type() of Q.positive(x), this
would be impossible, because then Q.positive couldn't be an instance
of Basic.
So instead, it has its own type, and the .func is set appropriately:
In [20]: type(Q.positive(x))
Out[20]: sympy.assumptions.assume.AppliedPredicate
In [21]: Q.positive(x).func
Out[21]: Q.positive
Ideally we would like to do the same thing with functions as well
(
https://github.com/sympy/sympy/issues/4787) so that it will be
possible to write things like cos + sin, and other "operator" like
expressions. sin + cos may end up not being a good idea, but as the
issue notes, something like D(f), where D is some kind of differential
operator, would be possible in this case (right now it isn't really
because f isn't an instance of Basic, so you can't just have D(f).args
== (f,)).
func has also been suggested as the way around issues with classes
that want to put non-Basic things in their args (particularly strings,
like with MatrixSymbol). Instead of MatrixSymbol('x', n, n).args ==
('x', n, n) as it is now, which is bad and breaks a lot of things
(because 'x' is not an instance of Basic), we would have
MatrixSymbol('x', n, n).args == (n, n) and MatrixSymbol('x', n,
n).func would be a special object that contains the 'x', which can
recreate the original MatrixSymbol('x', n, n).
Aaron Meurer
>
https://groups.google.com/d/msgid/sympy/fe2324dd-75b8-4f14-a21b-f9fcb192b2c5%40googlegroups.com.