-1

How can I iterate over function arguments without using *arg? I thought about making a list and then going over them. But this is too much work if I have a function with a lot of arguments. for example:

from typing import Union

def is_vormir_safe(threshhold: Union[int, float, complex], first_temp: Union[int, float, complex], \
                   second_temp: Union[int, float, complex], third_temp: Union[int, float, complex]) \
                   -> Union[int, float, complex]:
    count = 0
    # I want to iterate from the second function's argument to the last one
    for arg in arg[1:]:

I tried making a list for the arguments but this is too much work.

Eyal Cohen
  • 121
  • 6
  • 4
    If you have a function with a lot of arguments, then you should be using **arg. You've answered your own question. Why are you avoiding the simple solution? – Frank Yellin Mar 27 '23 at 20:53
  • you can have both positional args and the *arg collector... so defining something like `def is_vormir_safe(threshhold, *temps)` is totally possible. However, if you want to iterate over the parameters, that's the only way I believe is available. As an aside: This is exactly how class methods work. i.e. it's not unusual to see this syntax with `def my_class_foo(self, *args, **kwargs)` – David Culbreth Mar 27 '23 at 20:54
  • 4
    Having args with names like `first_temp` and `second_temp` is a very strong smell that you should just have a single iterable `temps` parameter (maybe a 3-tuple if it's very specifically 3 temperatures). That would simplify the function interface *and* your implementation. – Samwise Mar 27 '23 at 20:55
  • 2
    "Too much work" how? Do you mean too much work to describe for the type system? What part of it is requiring too much work? -- maybe we can address _that_, to find a way to do the Right Thing that _isn't_ too much work. Otherwise, this smells a lot like an [XY Problem](https://xyproblem.info/), where you're asking about an issue with your attempted solution instead of the real/underlying problem that drove you to attempt that solution in the first place. – Charles Duffy Mar 27 '23 at 21:01
  • Do you just want to introspect the function parameters inside the function? If so, you can use `is_vormir_safe.__code__.co_varnames` - potential duplicate of https://stackoverflow.com/questions/582056/getting-list-of-parameter-names-inside-python-function – match Mar 27 '23 at 21:12
  • 1
    @match that gets all the variables used by the function, not the function arguments – Tom McLean Mar 27 '23 at 21:14
  • 1
    @TomMcLean there's also `locals()` if they need the values as well as names. Though I was more just trying to work out OPs actual intent (I'm still not sure tbh...) – match Mar 27 '23 at 21:53
  • @match you should use the inspect module to get a functions args, then use locals to get the values of those args – Tom McLean Mar 28 '23 at 08:03

1 Answers1

0

Use a debugging-tool such as inspect.getfullargspec. To access to the actual value of the parameters, those passed when the function is called, check the content of the the frame.

Not recommended at all (the frame can be big!).

import inspect

def func(a, b, c, d=9):
    # get dict of variable of the local name space
    fr_loc = inspect.currentframe().f_locals
    # get the "parameters" identifiers
    args_id = inspect.getfullargspec(func).args
    # actual value
    args = [fr_loc[arg_id] for arg_id in args_id]
    print(args[1:])


func(*range(3))
#[1, 2, 9]

func(*range(4)) # change default value of d
#[1, 2, 3]

Remark: based on the comment of match, you can use locals() (as 1st statement in the function's body) instead of inspecting the frame object

cards
  • 3,936
  • 1
  • 7
  • 25