In python, how to call a function with an argument on a click event
Asked Answered
U

2

5

I created the code below, but when I click on the click me button I get the following error message:

TypeError: 'mpfr' object is not callable

Would someone know what is wrong with the code?

import gmpy2 as g
from ipywidgets import widgets
from IPython.display import display

button = widgets.Button(description="Click Me!")
display(button)

max_precision = g.get_max_precision()
pi = g.const_pi()
g.set_context(g.context())

def set_bits_precision(decimal_precision):
    bits_precision = int(decimal_precision/g.log(2))
    if (bits_precision > max_precision): bits_precision = max_precision
    ctx = g.get_context()
    ctx.precision = bits_precision
    return

def square_root(number):
    return g.sqrt(number)

def circle_perimeter(radius):
    return 2*pi*radius 

def on_button_clicked(x):
    return square_root(x)

set_bits_precision(10)
print(pi)
button.on_click(on_button_clicked(2))
Undesigning answered 20/6, 2018 at 15:5 Comment(3)
Usually 'object is not callable' usually means you have used a left-paren after an identifier. In your case perhaps you have 'mpfr (' when probably you meant something like 'mpfr, (' . That is, you are missing something (like a punctuation) after the mpfr.Ruse
button.on_click takes a callable as its argument. on_button_clicked(2) does not evaluate to a callable, it evaluates to a number (of type mpfr)Unpeopled
@ArtSwri No. That is not the issue at all. Did you even look at their code?Unpeopled
U
7

button.on_click must be given a callback function. You pass the result of on_button_clicked evaluated with parameter 2 (so, literally the square root of 2) instead of passing in a function. You can use partial function evaluation to do what you want, by replacing your last line of code with:

import functools
button.on_click(functools.partial(on_button_clicked, 2))
Unpeopled answered 20/6, 2018 at 16:1 Comment(4)
Interesting! But I'm getting the following error: "TypeError: on_button_clicked() takes 1 positional argument but 2 were given"Undesigning
@OlivierdeBroqueville on_click passes 1 argument to the callback. I'll edit my answer...Unpeopled
Thank you jbch. It's working fine now. I had to do the following changes to the on_button_clicked function >> def on_button_clicked(x, b):Undesigning
@OlivierdeBroqueville Yeah that will work, sorry I got busy elsewhere, probably wont have time to edit my answer for a while. Feel free to edit it or add your own answer with the correct code.Unpeopled
D
0

Getting help from this thread, I think defining a class is the best way to run functions by jupyter widgets:

import gmpy2 as g
from ipywidgets import widgets
from IPython.display import display


max_precision = g.get_max_precision()
pi = g.const_pi()
g.set_context(g.context())

class Test(object):
    
    def __init__(self):
        self.random_button = widgets.Button(
            description='Click Me!')
        self.random_button.on_click(self.on_button_clicked)
    
    
    def set_bits_precision(self,decimal_precision):
        bits_precision = int(decimal_precision/g.log(2))
        if (bits_precision > max_precision): bits_precision = max_precision
        ctx = g.get_context()
        ctx.precision = bits_precision
        self.val = ctx.precision
        print(self.val)

    def square_root(self,x):
        self.val = g.sqrt(x)
        print(self.val)

    def circle_perimeter(self,radius):
        self.val = 2*pi*radius
        print(self.val)

    def on_button_clicked(self,*args):
        self.square_root(x=4)
        self.circle_perimeter(radius=10)
        self.set_bits_precision(decimal_precision=10)

buttonObject = Test()
display(buttonObject.random_button)

You have to edit x, radius, and precision manually each time so that data become updated for the Button. Good luck.

Dispersive answered 14/7 at 10:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.