Wouter Wouter - 4 months ago 29
Python Question

TypeError: unsupported operand type(s) for ** or pow(): 'function' and 'int' probability calculator

I'm trying to put my probability calculator inside a nice GUI but I ran into a problem with my probability calculations.

I've made 3 scripts:


  1. Tkinter script, my user interface and also the place where I get
    my numbers from.

  2. My runable script, this script has been put in place to prevent
    circular imports. This is also the script that I run to use my
    "program"

  3. My probability calculator, it collects data from the Tkinter GUI,
    does a calculation and sends the output again to the Tkinter script
    to show the result in the GUI




Scripts

> Tkinter GUI, called testtennisGUI.py



from Tkinter import *
import ttk
import csv
import tennisGameProbability


def invullen():
resultaat.set(str(" Game = "+("{0:.2%}".format(tennisGameProbability.game_prob()))))


def result_first_service_percentage():
return calculate()

frame = Tk()


def calculate(*args):
try:
value_player1c = float(v1player1.get())/100
value_player1d = float(v2player1.get())/100
value_player1e = float(v3player1.get())/100
result_player_1.set(str("{0:.3}".format((((value_player1c * value_player1d)-(value_player1c * value_player1e)) + value_player1e)*100)))
return ((value_player1c * value_player1d)-(value_player1c * value_player1e)) + value_player1e
except ValueError:
pass

resultaat = StringVar()
resultaat2 = StringVar()
b1player1 = StringVar()
v1player1 = StringVar()
v2player1 = StringVar()
v3player1 = StringVar()
result_player_1 = StringVar()

c_player1 = Label(frame, text="1st Service Percentage:").grid(row=3, column=1, sticky='w')
cc_player1 = Entry(frame, text="value", textvariable=v1player1, justify='center', width=10).grid(row=3, column=2)
d_player1 = Label(frame, text="Points Won on 1st Serve: ").grid(row=4, column=1, sticky='w')
dd_player1 = Entry(frame, text="value", textvariable=v2player1, justify='center', width=10).grid(row=4, column=2)
e_player1 = Label(frame, text="Points Won on 2nd serve:").grid(row=5, column=1, sticky='w')
ee_player1 = Entry(frame, text="value", textvariable=v3player1, justify='center', width=10).grid(row=5, column=2)
projected_player1 = Label(frame, text="Projected Hold").grid(row=6, column=1, sticky='w')
my_result_player_1 = Entry(frame, textvariable=result_player_1, justify='center', width=10).grid(row=6, column=2)
my_resultaat = Label(frame, textvariable=resultaat, justify='center').grid(row=8, column=1, columnspan=2, pady=10)
my_resultaat_2 = Label(frame, textvariable=resultaat2, justify='center').grid(row=9, column=1, columnspan=2, pady=10)


f = open('testtennis.csv')
csv_f = csv.reader(f)
players_names = []
for row in csv_f:
players_names.append(row[0])


def new_selection(event):
return player1()

box_value = StringVar()
box = ttk.Combobox(frame, textvariable=box_value, justify='center')
box.bind("<<ComboboxSelected>>", new_selection)
box['values'] = players_names
box.current()
box.grid(column=2, row=1, pady=20, padx=15)


def player1():
with open("testtennis.csv") as fh:
for row in fh:
if (box_value.get()) in row:
player_name = row[0:row.find(',')]
row = row.replace(player_name+',', '')
first_service = row[0:row.find(",")]
row = row.replace(first_service+',', '')
points_first_serve = row[0:row.find(",")]
row = row.replace(points_first_serve + ',', '')
points_second_serve = row[0:row.find(",")]
row.replace(points_second_serve + ',', '')
v1player1.set(first_service)
v2player1.set(points_first_serve)
v3player1.set(points_second_serve)


run = ttk.Button(frame, text='Run', command=invullen)
run.grid(column=1, row=7, columnspan=2, ipadx=15, pady=25)
mainloop()



The script that I run, called run_file.py


import testtennisGUI


def projected_hold_player1():
return testtennisGUI.result_first_service_percentage()


The calculation script, called tennisGameProbability.py

from run_file import projected_hold_player1


def fact(x):
if x in [0, 1]:
return 1
r = 1
for a in range(1, (x + 1)):
r = r * a
return r


def ch(a, b):
return fact(a) / (fact(b) * fact(a - b))
pass


def game_outcome(s, a, b):
return ch((a + b), a) * (s ** a) * ((1 - s) ** b) * s


def game_prob(s=projected_hold_player1, v=0, w=0):
if v >= 4 and (v - w) >= 2:
return 1
elif w >= 4 and (w - v) >= 2:
return 0
else:
pass
while True:
if (v + w) > 6:
v -= 1
w -= 1
else:
break
if w == 0:
w0 = game_outcome(s, 3 - v, 0)
else:
w0 = 0
if w <= 1:
w15 = game_outcome(s, 3 - v, 1 - w)
else:
w15 = 0
if w <= 2:
w30 = game_outcome(s, 3 - v, 2 - w)
else:
w30 = 0
if v == 4:
wad, lad = s, 0
d = 1 - s
elif w == 4:
wad, lad = 0, 1 - s
d = s
else:
wad, lad = 0, 0
a = 3 - v
b = 3 - w
d = ch((a + b), a) * (s ** a) * ((1 - s) ** b)
if v <= 2:
l30 = game_outcome((1 - s), 3 - w, 2 - v)
else:
l30 = 0
if v <= 1:
l15 = game_outcome((1 - s), 3 - w, 1 - v)
else:
l15 = 0
if v == 0:
l0 = game_outcome((1 - s), 3 - w, 0)
else:
l0 = 0
denom = s ** 2 + (1 - s) ** 2
wd = (d * (s ** 2)) / denom
ld = (d * ((1 - s) ** 2)) / denom
win = w0 + w15 + w30 + wd + wad
lose = l0 + l15 + l30 + ld + lad
return win
return game_prob()


The error I'm getting is:

File "C:\Users\Magali\PycharmProjects\Wouter\tennisGameProbability.py", line 19, in game_outcome
return ch((a + b), a) * (s ** a) * ((1 - s) ** b) * s
TypeError: unsupported operand type(s) for ** or pow(): 'function' and 'int'


When I manully put in values in the tennisGameProbability script than it works.
So I think the issue is with the way my variable data gets moved between the scripts. I've tried everything I know but without any luck.

Who can tell me where my mistake is?

Answer

You are clearly assigning the default value of s as a function:

from run_file import projected_hold_player1

...

def game_prob(s=projected_hold_player1, v=0, w=0)
#             ^^^^^^^^^^^^^^^^^^^^^^^^

So calling s**a raises that error, as the operator does not specify any behavior for function types.

You should instead assign s to the return value of the function projected_hold_player1, provided the value is a number, which I think it is.

def game_prob(s=None, v=0, w=0):
    if s is None:
         s = projected_hold_player1()

Or you could call the function while assigning the default value.

def game_prob(s=projected_hold_player1(), v=0, w=0)
#                                     ^^