0

I have a function like so:

def ease_bounce_out(t, bounces=None):
    if bounces is None:
        bounces = [4 / 11, 6 / 11, 8 / 11, 3 / 4, 9 / 11, 10 / 11, 15 / 16, 21 / 22, 63 / 64]

    bounces.insert(0, 1 / bounces[0] / bounces[0])
    if t < bounces[1]:
        return bounces[0] * t * t
    else:
        for i in range(3, len(bounces) - 2, 3):
            if t < bounces[i]:
                t -= bounces[i - 1]
                return bounces[0] * t * t + bounces[i + 1]

    t -= bounces[len(bounces) - 2]
    return bounces[0] * t * t + bounces[len(bounces) - 1]

and I would like to compact it all down into 1 string so that I can use the eval() function to get an output for any value of t. I have an example of an easier function:

def ease_poly(t, power=2):
    t *= 2
    if t < 1:
        return t ** power
    else:
        return 2 - ((2 - t) ** power)

would become:

def ease_poly(power=2):
    return f"(t * 2) ** {power} if (t * 2) < 1 else 2 - ((2 - (t * 2)) ** {power})"

This way, I could use this string and evaluate the function for any value of t by simply doing:

ease = ease_poly(power=3)
t = 0.4  # 0 <= t <= 1
print(eval(ease)) 

Now to get started with my question, it doesn't actually have to be 1 line, this is what I've been thinking of:

def ease_bounce_out(bounces=None):
    if bounces is None:
        bounces = [4 / 11, 6 / 11, 8 / 11, 3 / 4, 9 / 11, 10 / 11, 15 / 16, 21 / 22, 63 / 64]

    return # some code here that compiles the rest into a string
Bhavye Mathur
  • 1,024
  • 1
  • 7
  • 25
  • I don’t understand why you’d want to use `eval` here at all. Just evaluate the actual function! Using `eval` is likely a (very) bad solution. – Konrad Rudolph Jul 06 '20 at 11:39
  • yes indeed, but it's what I require for my project. You see, I won't be using this function, it's for a graphics framework I'm building (https://github.com/BhavyeMathur/goopy) through which the user will say something like ```object.animate(..., ease=ease_poly(power=2), ...)```. This can then be evaluated for any value of ```t``` in the backend while allowing the user to enter the easier statement rather than ```ease=ease_poly, args=(2,)```. – Bhavye Mathur Jul 06 '20 at 11:42
  • When using an IDE, it's also easier for the user to then see what args they can give the function rather than entering them separately – Bhavye Mathur Jul 06 '20 at 11:43
  • If that’s the case, you’ll want to return a *function* from your function, not a string. In particular, what you want is called a *closure*. – Konrad Rudolph Jul 06 '20 at 11:44
  • ohhh... let me look into it. – Bhavye Mathur Jul 06 '20 at 11:44
  • Yes, that is indeed what I am looking for! Can't believe I didn't think of it. Thanks! Perhaps you can post this as an answer so that I can approve it :) – Bhavye Mathur Jul 06 '20 at 11:46

1 Answers1

1

A small tip,

  1. bounces[ -1 ] = Last item

    bounces[ -2 ] = Last second item

    Don't use bounces[ len(bounces) - 1 ]

Answer: You can't have that string answer with eval. Because your function is making decisions based on t. You have to pass t.

If evaluating for all t is your primary concern then other way could help. Forget about eval. Don't pass t but use t in function then it will look up in global scope and uses t in that scope.

Example:

This function requires t to be passed.

def mathuer(t, b = 23 ):
    x = t
    if b > t:
        x = t
    return x

This function uses global t.

def mathuer(b = 23 ):
    x = t
    if b > t:
        x = t
    return x

This is how it works,

t = 34
obj = mathuer() // Uses t defined above
  • Ahhh yes, negative index numbers. This code was written some time ago and I learnt about them embarrassingly late. but thanks! – Bhavye Mathur Jul 06 '20 at 12:36