Is everything object in Python?

Asked

Viewed 1,093 times

13

I am very confused about what is an object and what can behave as an object, see the example I created to illustrate the situation:

def subtrai(x,y):
    return (x - y)

class OpeMatematica(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def soma(self):
        return (self.x + self.y)

soma = OpeMatematica(10,10)
print(soma.soma())

print(subtrai(100, 10))

s = subtrai
print(s(50,10))

s = soma
s.x = 10
s.y = 100
print(s.soma())

I created a function subtrai performing a subtraction and creating a class OpeMatematica with the attributes x and y and a method soma.

In this line:

soma = OpeMatematica(10,10)
print(soma.soma())

I established my class OpeMatematica and invoked the method soma and I got the result 20.

In this line:

print(subtrai(100, 10))

I invoked the function subtrai and I got the result 90.

In this line I discovered something interesting:

s = subtrai
print(s(50,10))

See that I assign the variable s the function subtrai and the same began to assume the behavior of the function subtrai see s(50,10), is as if the function subtrai were an object and could be instantiated, the result of the operation is 40.

And in this line has another curiosity:

s = soma
s.x = 10
s.y = 100
print(s.soma())

Assigns to s the object soma and s became an object of the type OpeMatematica, accessing the attributes x and y and invoking the method soma, the result obtained is 110.

Now I’m confused about what is a Python object, analyzing this code I concluded that everything seems to be a Python object even variables and function, could someone explain to me why Python has this behavior, and what is an object or a class in Python?

1 answer

16


That’s a very different concept. That means that the Python functions are first class. That is, among other features the function can be assigned to a variable (obviously it can also be passed as argument or function return). The function (code) itself is treated as if it were a value, a given. In general this is done with anonymous functions or Amble, but it is possible to do the same directly in an existing function, as was done in the example.

In this case the variable will store the function and not a result of it. The type of this variable is FunctionType. It is clear that concretely it does not keep the source code of the function (even could, but I do not know any language that does it, would be inefficient and risky), there are mechanisms that refer to the function and the compiler/interpreter knows how to treat this variable differently, and its access is given as a function call, since it is a function.

This concept has nothing to do with object orientation. But it may be that the internal way of storing the function in the variable is through an object (still not even using OOP). The most traditional, especially when it is not a closure, is that it is only one pointer. In the case of Python there really is an object controlling this, but it is an object like any other. One of its members is the __call__ that allows you to make the call.

In Python not everything is an object in the sense that people expect, the class syntax itself already gives a hint that needs to be explicit about it. Leaving aside OOP, the concept of the type object, in a certain way, we can say that everything in any language is an object. If it’s not an object, then what? Of course, this terminology may be strange to some, but it’s real. In C you have objects, they’re just not the same as in Java, for example.

A function has an infrastructure on an object that allows it to be stored on it and then called. This is an internal mechanism that guarantees the call. As everything in computing there is no magic, there is engineering. Someone saw a problem, and found a viable solution to solve the problem.

One of the ways to call a function stored in an object is through the compiler calling the function using the variable directly. With the help of the compiler the call becomes more convenient and elegant, as shown in the question.

If you’re not sure if you can call her, you can check before:

s = 0
if hasattr(s, '__call__')
    s(50, 10)

This will not call anything and will not give error, because in this example the variable s It’s not "searchable," it’s an integer, not a function. Checking whether the variable could be called as a function was done before calling, avoiding the error. This way allows you to conveniently solve a lot of problems without resorting to object orientation.

  • I don’t quite understand the purpose of callable(s) and the hasattr(s, '__call__') could you explain to me?

  • 1

    See if you’ve improved.

  • I can understand now.

  • The function callable serves to test whether an object can be invoked or not, it returns True or False. Therefore it cannot be used to invoke methods/functions nor in Python 2 or in the Python 3.

  • 1

    @fernandosavio took this part, I was confusing more than helping even.

  • I think I could change if hasattr(s, '__call__') for if callable(s)... This way is more correct, despite the discussion be a little long, callable checks Pyobject in C to see if it can be invoked (I believe this field) and has_attr may have problems in specific cases.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.