¿Qué significa cuando se omiten los paréntesis en una función o llamada a un método?
Tengo este código de ejemplo:
class objectTest():
def __init__(self, a):
self.value = a
def get_value(self):
return self.value
a = objectTest(1)
b = objectTest(1)
print(a == b)
print(a.get_value() == b.get_value)
print(a.get_value() == b.get_value())
print(a.get_value == b.get_value)
Los resultados mostrados son:
False
False
True
False
¿Por qué esto no causa un error ? get_value
es un método, entonces ¿por qué podemos usarlo así sin llamarlo primero?
Ver también : En Python, ¿qué significa '<función en...>'?
Como se mencionó, las funciones y los métodos son objetos de primera clase. Los llamas colocando algunos paréntesis (corchetes) al final. Pero parece que quieres más motivación sobre por qué Python nos permite hacer eso. ¿Por qué debería importarnos si las funciones son de primera clase o no?
A veces no quieres llamarlos, quieres pasar una referencia al propio invocable.
from multiprocessing import Process
t = Process(target=my_long_running_function)
Si coloca corchetes después de lo anterior, se ejecutará my_long_running_function
en su hilo principal; ¡Difícilmente lo que querías! Quería dar Process
una referencia a su invocable para que se ejecute solo en un nuevo proceso.
A veces solo quieres especificar el invocable y dejar algo más...
def do_something(s):
return s[::-1].upper()
map(do_something,['hey','what up','yo'])
Out[3]: ['YEH', 'PU TAHW', 'OY']
( map
en este caso) complete sus argumentos.
Tal vez solo desee colocar un montón de invocables en alguna colección y recuperar el que desee de manera dinámica.
from operator import *
str_ops = {'<':lt,'>':gt,'==':eq} # etc
op = str_ops.get(my_operator)
if op:
result = op(lhs,rhs)
Lo anterior es una forma de asignar representaciones de cadenas de operadores a su acción real.
Las funciones y métodos en Python también son objetos en sí mismos. Por lo tanto, puedes compararlos como lo harías con cualquier otro objeto.
>>> type(a.get_value)
<type 'instancemethod'>
>>> type(a.get_value())
<type 'int'>
Normalmente, por supuesto, no compararías métodos entre sí ni con ninguna otra cosa, porque no es muy útil. Un lugar en el que resulta útil es cuando desea pasar una función a otra función. Un uso común es ordenar una cadena que no distingue entre mayúsculas y minúsculas diciéndole que la use str.lower
como método para generar la clave de clasificación:
>>> list_of_strings=['A','b','C']
>>> sorted(list_of_strings)
['A', 'C', 'b']
>>> sorted(list_of_strings, key=str.lower)
['A', 'b', 'C']
def mul(a, b):
return a * b
def add(a, b):
return a + b
def do(op, a, b):
return op(a, b)
do(add, 2, 3) # return 5
print(a.get_value() == b.get_value) # 1
print(a.get_value() == b.get_value()) # 2
print(a.get_value == b.get_value) # 3
1) ¿El valor de retorno de la llamada es a.get_value()
igual al método b.get_value
?
2) ¿ a.get_value()
Devuelve lo mismo que b.get_value()
?
3) ¿Es la referencia del método a.get_value
igual a la referencia del método b.get_value
?
Esto es Python perfectamente válido :)
Varios comentaristas quieren un ejemplo de dónde esto resulta útil. Una aplicación está en subprocesos. Necesitamos pasar el objetivo al hilo sin usar corchetes. De lo contrario, el objetivo se crea en el hilo principal, que es lo que intentamos evitar.
Ejemplo:
En test1.py llamo a ThreadTest sin usar corchetes. test_thread comienza en el hilo y permite que test1.py continúe ejecutándose.
En test2.py, paso ThreadTest() como objetivo. En este caso, el hilo no permite que test2.py continúe ejecutándose.
prueba1.py
import threading
from thread_test import ThreadTest
thread = threading.Thread(target=ThreadTest)
thread.start()
print('not blocked')
prueba2.py
import threading
from thread_test import ThreadTest
thread = threading.Thread(target=ThreadTest())
thread.start()
print('not blocked')
test_thread.py
from time import sleep
class ThreadTest():
def __init__(self):
print('thread_test started')
while True:
sleep(1)
print('test_thread')
salida de test1.py:
thread_test started
not blocked
test_thread
test_thread
test_thread
salida de test2.py:
thread_test started
test_thread
test_thread
test_thread
Estoy usando python3.5 en Linux Mint.