Both NumPy and pandas datatypes get printed very differently even though we are just passing the data to the print function rather than calling a method
https://numpy.org/doc/stable/reference/generated/numpy.set_printoptions.html
Both NumPy and pandas datatypes get printed very differently even though we are just passing the data to the print function rather than calling a method
https://numpy.org/doc/stable/reference/generated/numpy.set_printoptions.html
Every full-featured data type has conversion functions for conversion to string, __str__, and output, __repr__.  Both PANDAS and NumPy have implemented those methods as part of each data type's class definition -- those control how the data types appear.
You can look up details in any mid-level tutorial on classes.
Prune's answer is correct, but I want to make it more concrete with an example.
The print function actually outputs whatever is returned by the instance's class's __repr__ magic method
example:
let's say you have a Person class:
class Person:
    pass
p = Person()
print(p)
The result will be something like:
<__main__.Person object at 0x000000D9D5034508>
Now let's implement the __repr__ magic method:
class Person:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return f"< Person Name: {self.name} >"
p = Person("Robert")
print(p)
I also added the constructor to demonstrate how one may use it. The result will be:
< Person Name: Robert >
And that's how Numpy and Pandas are able to display the array and Dataframes like that.
__str__methods of the various classes