0

Suppose the code below:

from functools import partial
import random

def integer(min=1, max=10):
    return random.randint(min, max)

def double(min=1, max=10):
    return random.uniform(min, max)

if __name__ == '__main__':
    p1 = partial(integer, 5, 10)
    p2 = partial(double, 5, 10)
    for f in [p1, p2]:
        f() # I'd like to know if there's a different way to call this like `call(f)` or something

As mentioned in the comment, I'd like to know if there's a way to call f without using parentheses. One step further, suppose I can call f without using parentheses, if I would like to pass additional parameters to f, how do I go about it (like call(f, additional_param_1, additional_param_2))?

Thank you in advance for your answers!

user1330974
  • 2,500
  • 5
  • 32
  • 60
  • 1
    I get a TracebackError when running your code on Line 14. –  Aug 07 '19 at 01:33
  • 1
    Why? Are you just playing with Python syntax, or do you have some concrete reason to do this? – ChrisGPT was on strike Aug 07 '19 at 01:33
  • 2
    There is `f.__call__()` but I doubt that's what you're after. Why do you want to be able to do `call(f, arg1, arg2)`? What problem are you really trying to solve, because there probably is a way that doesn't involve a `call()` function - although you could write such a function quite easily yourself. – Grismar Aug 07 '19 at 01:41
  • 1
    @Cygnus that line should be `p1 = partial(integer, 5, 10)` – Aaron Aug 07 '19 at 01:44
  • @Cygnus fixed the typo. Sorry about that. – user1330974 Aug 07 '19 at 01:58
  • @Chris I am just playing with Python syntax. I saw something like `apply` in `pandas`, so I was wondering if there's such meta level function call that calls a `partial` like so. Thank you. – user1330974 Aug 07 '19 at 02:00
  • You could always just use `print(f())`. You still use `f()` but the print in front makes it look nicer imo. –  Aug 07 '19 at 02:07
  • 2
    @user1330974 no, there isn't. There used to be an `apply` function in Python 2, but even then it was considered obsolete probably decades ago. Why would you ever need this? – juanpa.arrivillaga Aug 07 '19 at 02:10
  • @juanpa.arrivillaga Thank you. I answered why I would ever need this in the comment in the answer below. – user1330974 Aug 07 '19 at 02:18

1 Answers1

1

Not in base Python, but you can easily write call() yourself:

from functools import partial
import random

def integer(min=1, max=10):
    return random.randint(min, max)

def double(min=1, max=10):
    return random.uniform(min, max)

def call(f, *args, **kwargs):
    return f(*args, **kwargs)

if __name__ == '__main__':
    p1 = partial(integer, 5, 10)
    p2 = partial(double, 5, 10)
    for f in [p1, p2]:
        call(f)

Note: you have a typo in your example, you're calling partial on int, but your function is called integer. (neither is a very good name and I think you're trying to solve a problem that you're not stating, that has a better solution)

Grismar
  • 27,561
  • 4
  • 31
  • 54
  • 1
    I mean it makes no sense to do this in the first place, but might it be better to return the results of the function f from the call function as well? – Aaron Aug 07 '19 at 01:49
  • ...which is why I asked OP what they're trying to accomplish. This smells like an [XY problem](https://meta.stackexchange.com/q/66377/248627). – ChrisGPT was on strike Aug 07 '19 at 01:56
  • @Aaron could you please elaborate a little more on what you mean by 'return the results of the function `f` from the call function'? Thank you. – user1330974 Aug 07 '19 at 02:01
  • 1
    @user1330974 they mean actually `return` the results, currently, `call` will **always return `None`** – juanpa.arrivillaga Aug 07 '19 at 02:10
  • @juanpa.arrivillaga I want to generate random integer and double/float based on a string (commandline) input from user. For example, `python myprog.py -i 'integer(1,10), double(1.0,10.0)'`, then `myprog.py` will parse the input string, create partials, and then return the results of calling these functions, for example, in a tuple. In addition, I want to generate, say, 1000 tuples in a row in a lazy way. Hope that makes sense. I am good with calling the partial with parentheses, but I was wondering if there's a 'cleaner' way. Thank you. – user1330974 Aug 07 '19 at 02:17
  • 1
    Added a `return`, but of course there's still all kinds of issues with generators, asynchronous functions, etc. It's really not something you should do, unless you have a very specific use for it. @user1330974 the 'clean' way of doing things is to follow convention - in Python, that means clearly calling a function when you need it, with parentheses. Cleaner doesn't always mean fewer symbols. – Grismar Aug 07 '19 at 07:24
  • 1
    @user1330974 again, calling the script with code like that is a massive anti-pattern and there's very little use for it that could not be achieved in safer and more efficient ways. You'd do well to learn to write the language as it was intended, instead of trying to subvert it in unreadable and unpredictable spaghetti code. – Grismar Aug 07 '19 at 07:26
  • @Grismar Thank you for the word of advice and caution. – user1330974 Aug 07 '19 at 13:44
  • 1
    @user1330974 You could use eval to execute functions like that, however allowing the user to execute arbitrary python is a big security risk, so it should not be done if anyone other than you is using the script. https://docs.python.org/3/library/functions.html#eval – Aaron Aug 08 '19 at 14:27
  • @Aaron I agree. That's why I am not using `eval` although I know it is one of the easiest route to go with. Thank you for your input. – user1330974 Aug 08 '19 at 18:15