Skip to content Skip to sidebar Skip to footer

What Distinguishes A Command From Needing () Vs Not?

I recently spent way too long debugging a piece of code, only to realize that the issue was I did not include a () after a command. What is the logic behind which commands require

Solution 1:

Because functions need parenthesis for their arguments, while variables do not, that's why it's list.append(<item>) but it's list.items.

If you call a function without the parenthesis like list.append what returns is a description of the function, not a description of what the function does, but a description of what it is.

As for classes, a call to a class with parenthesis initiates an object of that class, while a call to a class without the parenthesis point to the class itself, which means that if you were to execute print(SomeClass) you'd get <class '__main__.SomeClass'> which is a description of what it is, the same kind of response you'd get if you were to call a function without parenthesis.

Solution 2:

What's the logic behind which commands use a () and which do not?

An object needs to have a __call__ method associated with it for it to called as a function using ():

classTest:
    def__call__(self, arg):
        print("Called with", arg)

t = Test()  # The Test class object uses __call__ to create instances
t(5)  # Then this line prints "Called with 5"

So, the difference is that columns doesn't have a __call__ method defined, while Index and DataFrame do.

Solution 3:

TL;DR you just kinda have to know

Nominally, the parens are needed to call a function instead of just returning an object.

foo.bar    # get the bar object
foo.bar()  # call the bar object 

Callable objects have a __call__ method. When python sees the (), it knows to call __call__. This is done at the C level.

In addition, python has the concept of a property. Its a callable data object that looks like a regular data object.

classFoo:
    def__init__(self):
        self._foo = "foo"    @propertydeffoo(self):
        return"I am " + self._foo

    @foo.setterdeffoo(self, val):
        assertisinstance(val, str)
        self._foo = val + " you bet"

f = Foo()
f.foo = "Hello"# calls setterprint(f.foo)        # calls getter

Similarly, when python sees array notation foo[1] it will call an object's __getitem__ or __setitem__ methods and the object is free to overload that call in any way it sees fit.

Finally, the object itself can intercept attribute access with __getattr__, __getattribute__ and __setattr__ methods, leaving everything up in the air. In fact, python doesn't really know what getting and setting attributes means. It is calling these methods. Most objects just use the default versions inherited from object. If the class is implemented in C, there is no end to what could be going on in the background.

Python is a dynamic language and many packages add abstractions to make it easier (?) to use their services. The downside is that you may spend more time with help text and documentation than one may like.

Solution 4:

Object method vs Object attribute.

Objects has methods and attributes. Methods require a parenthesis to call them -- even if the method does not require arguments. Where as attributes are like variables are pointed to objects as the program progresses. You just call these attributes by their name (without parenthesis). Of course you may have to qualify both the methods and attributes with the object names as required.

Post a Comment for "What Distinguishes A Command From Needing () Vs Not?"