[Tutor] What's the difference between calling a method with parenthesis vs. without it?

Steven D'Aprano steve at pearwood.info
Mon Jun 18 06:22:55 EDT 2018


Another thought comes to mind...

On Sun, Jun 17, 2018 at 02:02:07PM -0400, C W wrote:

> Obviously, the second case does not make any senses. But, in data.columns,
> it is only correct to do without parenthesis as below:
> 
> > data.columns
[...]
> # with parenthesis throws an error
> > data.columns()


That's because data.columns isn't a method. Since it isn't a method, it 
is just a regular attribute (or possibly a read-only attribute) that you 
can retrieve the contents, but not call.

Some languages call these "instance variables". I don't like that term, 
but in this case the analogy with variables is good. Consider two named 
objects, one which is a function, one which is not:

py> len
<built-in function len>
py> len("hello world")  # try calling len
11

py> length = 99
py> length()  # try calling length
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable


The reason for this should be fairly obvious, but I trust you can see 
that *in general* there is no fool-proof way of knowing which names 
refer to callable functions and which refer to non-callable values. You 
have to know the context of the code, read the documentation or manual, 
or just try it and see what happens.

The same can apply to methods and other attributes:

class MyClass:

    length = 99

    def len(self, object):
        # Re-invent the wheel, badly.
        count = 0
        for item in object:
            count += 1
        return count



And now to see the same behaviour as for ordinary variables:


py> instance = MyClass()
py> instance.length
99
py> instance.length()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

py> print(instance.len)
<bound method MyClass.len of <__main__.MyClass object at 0xb79009cc>>
py> instance.len("hello world")
11


Does this help you understand what you are seeing with the data.columns 
example?


-- 
Steve


More information about the Tutor mailing list