Why is this function not callable?

Here:

def point(a, b):
    foo = (a,b)
    return foo
pointcall = point(9,7)

print(callable(pointcall))

This returns False. I’m not sure why it isn’t callable.

To be callable, pointcall needs to be a reference, not a return.

The return is a tuple, not a function. That means pointcall cannot be used as a callback.


Consider,

>>> def point(x, y):
    return x, y

>>> def slope(*points):
    a, b = points
    h, i = a
    j, k = b
    return float(k - i) / float(j - h)

>>> slope(point(25, 10), point(50, 40))
1.2
>>> 

This is Python 2, btw, but worth the think.


>>> def yintercept(*points):
	m = slope(*points)
	x, y = points[0]
	return y - m * x

>>> def xintercept(*points):
	m = slope(*points)
	b = yintercept(*points)
	return .0 - b / m

>>> yintercept(point(25, 10), point(50, 40))
-20.0
>>> xintercept(point(25, 10), point(50, 40))
16.666666666666668
>>> slope(point(0, -20), point(16.666666, 0))
1.200000048000002
>>> slope(point(0, -20), point(16.6666666666666666, 0))
1.2
>>> 

We drew out the interpreter. It was forced to round once we got past 15 decimal places. Even the internals have their limits.

>>> slope(point(0,-20),point(16+xintercept(point(25,10),point(50,40))%1,0))
1.2
>>> 

Gather together the concepts we’ve covered. Backtrack if you must, and now would be the time to do it. We’re pressing forward. There is no hurry.

So is your point function callable?
If not, how can you make it callable?

def point(a, b):
    foo = (a,b)
    return foo
pointcall = point(9,7)

point(9, 7) is not a (callable) function , it is a (non-callable) tuple, namely (9, 7)

The function is not point(9, 7), but rather point.

def point(a, b):
    foo = (a,b)
    return foo
pointcall = point(9,7)

print("pointcall ", pointcall)
print("pointcall type ", type(pointcall))
print("pointcall is callable ", callable(pointcall))
print("****")
print("point type ", type(point))
print("point ", point)
print("point is callable ", callable(point))

Output:

pointcall  (9, 7)
pointcall type  <class 'tuple'>
pointcall is callable  False
****
point type  <class 'function'>
point  <function point at 0x03BC6390>
point is callable  True

Now, you can assign the function point to a variable. Just omit the parentheses. Now the assignment does not run point() first, it just assigns the entire function.

def point(a, b):
    foo = (a,b)
    return foo
pointcall = point

new_call = pointcall(9, 7)

print("pointcall ", pointcall)
print("pointcall type ", type(pointcall))
print("pointcall is callable ", callable(pointcall))
print("****")
print("new_call ", new_call)
print("new_call type ", type(new_call))
print("new_call is callable ", callable(new_call))

Output:

pointcall  <function point at 0x03CF6390>
pointcall type  <class 'function'>
pointcall is callable  True
****
new_call  (9, 7)
new_call type  <class 'tuple'>
new_call is callable  False