DataFrame issue (parenthesis)
You understand it well, in general parenthesis call class method, and without you call an attribute.
In your exemple you don't have an error, because df.head is bound to NDFrame.head who is a method as well. If df.head was only a method, calling it without parenthesis will raise an AttributeError.
May I ask what's the difference between df.head() and df.head in python's syntax nature? Could I interpret as the former one is for calling a method and the later one is just trying to obtain the DataFrame's attribute, which is the head? I am so confused why sometimes there is a parenthesis at the end but sometimes not... Thank you so much.