1===============================
2Classification of SymPy objects
3===============================
4
5There are several ways of how SymPy object is classified.
6
7class
8=====
9
10Like any other object in Python, SymPy expression is an instance of class. You can
11get the class of the object with built-in `type()` function, and check it with
12`isinstance()` function.
13
14    >>> from sympy import Add
15    >>> from sympy.abc import x,y
16    >>> type(x + y)
17    <class 'sympy.core.add.Add'>
18    >>> isinstance(x + y, Add)
19    True
20
21Classes represent only the programmatic structures of the objects, and does not
22distinguish the mathematical difference between them. For example, the integral
23of number and the integral of matrix both have the class `Integral`, although the
24former is number and the latter is matrix.
25
26    >>> from sympy import MatrixSymbol, Integral
27    >>> A = MatrixSymbol('A', 2, 2)
28    >>> type(Integral(1, x))
29    <class 'sympy.integrals.integrals.Integral'>
30    >>> type(Integral(A, x))
31    <class 'sympy.integrals.integrals.Integral'>
32
33kind
34====
35
36Kind indicates what mathematical object does the expression represent.
37You can retrieve the kind of expression with `.kind` property.
38
39    >>> Integral(1, x).kind
40    NumberKind
41    >>> Integral(A, x).kind
42    MatrixKind(NumberKind)
43
44This result shows that `Integral(1, x)` is number, and `Integral(A, x)` is matrix with number element.
45
46Since the class cannot guarantee to catch this difference, kind of the object is very important.
47For example, if you are building a function or class that is designed to work only for
48numbers, you should consider filtering the arguments with `NumberKind` so that the user
49does not naively pass unsupported objects such as `Integral(A, x)`.
50
51For the performance, set theory is not implemented in kind system. For example,
52
53    `NumberKind` does not distinguish the real number and complex number.
54
55    >>> from sympy import pi, I
56    >>> pi.kind
57    NumberKind
58    >>> I.kind
59    NumberKind
60
61    SymPy's `Set` and kind are not compatible.
62
63    >>> from sympy import S
64    >>> from sympy.core.kind import NumberKind
65    >>> S.Reals.is_subset(S.Complexes)
66    True
67    >>> S.Reals.is_subset(NumberKind)
68    Traceback (most recent call last):
69    ...
70    ValueError: Unknown argument 'NumberKind'
71
72sets and assumptions
73====================
74
75If you want to classify the object in strictly mathematical way, you may need
76SymPy's sets and assumptions.
77
78    >>> from sympy import ask, Q
79    >>> S.One in S.Reals
80    True
81    >>> ask(Q.even(2*x), Q.odd(x))
82    True
83
84See `assumptions` module and `sets` module for more information.
85
86func
87====
88
89`func` is the head of the object, and it is used to recurse over the expression tree.
90
91    >>> Add(x + y).func
92    <class 'sympy.core.add.Add'>
93    >>> Add(x + x).func
94    <class 'sympy.core.mul.Mul'>
95    >>> Q.even(x).func
96    <class 'sympy.assumptions.assume.AppliedPredicate'>
97
98As you can see, resulting head may be a class or another SymPy object.
99Keep this in mind when you classify the object with this attribute.
100See :ref:`tutorial-manipulation` for detailed information.
101