In this code:
import numpy as np
a = np.array([1,2,3])
b = np.array([2,3,4])
c = np.divide(a,b)
d = np.divide.outer(a,b)
e = np.outer(a,b)
print(f"{c=}\n{d=}\n{e=}")
It seems that numpy.divide
contains outer
, meanwhile numpy.divide
is a function.
I’m really confused why numpy.divide
behaves like both class
(because it could contain something) and function
(because it is callable).
print(type(np.divide))
returns <class 'numpy.ufunc'>
. But why ufunc
could have this effect?
My question is that: why np.divide
is callable, meanwhile there is functions that is belongs to np.divide
? sys.stderr.write
is not a similar case as sys.stderr
is not callable.
An easy way to answer this type of question:
import numpy as np
print(type(np.divide))
Result:
<class 'numpy.ufunc'>
How can you call a class, or rather an instance of it? If a class has __call__
, it instances can be called, and this ufunc
is callable:
print(type(np.divide.__call__))
Result:
<class 'method-wrapper'>
It's not just that "a similar notation is used" - the instance is callable, no different from a function. A regular Python function is just an instance of the function class:
def fun():
...
print(type(fun))
print(type(fun.__call__))
Result:
<class 'function'>
<class 'method-wrapper'>
So, numpy.divide
is both a function and an object, which is an instance of a class. If something has the type class 'something'
, it's not itself a class, it's an instance of that class, an object.