-2

I have create a sample function where I want to pass all the keys in dict third_party to eval statement. Using itemgetter is not possible as dictionary key are variable.

def sample(third_party):
    '''
    :param third_party: is a dictionary number of keys and exact keys name varies
    '''
    #Types can be of multiple type, using if/else not possible
    #type will always a key
    tp_type = third_party['type']
    if tp_type[-1] == 's':
        type_execution = tp_type + '_s'
    else:
        type_execution = tp_type + 's'
    #How to destructure dictionary into eval command as function arguments
    eval_statement = "inital.constant.command" + type_execution +  ".create("**third_party")"
    eval(eval_statement)
ddejohn
  • 8,775
  • 3
  • 17
  • 30
user
  • 2,694
  • 6
  • 24
  • 25

1 Answers1

2

Short answer: there's no syntactical sugar for what you're trying to do, as far as I'm aware.

Here's one way you can achieve your desired result though:

args = ", ".join(f"{k}={v}" for k, v in third_party.items())
eval_statement = f"inital.constant.command{type_execution}.create({args})"

That said, it's not really clear why you need to use eval(). Note that using eval() is generally considered bad practice so I strongly recommend reconsidering your approach to this problem.

For instance, if third_party["type"] returns the actual name of an attribute of the initial.constant object, whatever it is, you could simply do

exec_type = third_party["type"]
func = getattr(initial.constant, f"command{exec_type}")
func.create(**third_party)

Here's a simple demo:

In [1]: class A:
   ...:     def f(self, x):
   ...:         return x**2
   ...:
   ...:     def g(self, x):
   ...:         return x**3
   ...:

In [2]: a = A()

In [3]: getattr(a, "f")
Out[3]: <bound method A.f of <__main__.A object at 0x0000019A291D3790>>

In [4]: f = getattr(a, "f")

In [5]: f(3)
Out[5]: 9

But without knowing what your data look like, and what the objects you're working with look like I can't say for sure.

ddejohn
  • 8,775
  • 3
  • 17
  • 30
  • Having all methods store in dictionary is better than if/else. But these type are around 50. Want to know if some thing better exists. – user Sep 14 '21 at 04:28
  • Yeah, I mean assuming you have a limited number of methods, it's vastly more superior than needing to use `eval()`. – ddejohn Sep 14 '21 at 04:29
  • Aye, that downvote was me. The eval just shows the user how to shoot themselves in the foot. Building dictionary is not helpful in the case the ??> are unknown ahead of time (or there are very many of them), i.e. that is not a truly dynamic solution. The obvious dynamic approach that your answer is missing is using `getattr` for the "type_execution". But actually, I don't think this question should be answered at all (yet) because it has a syntax error and isn't clear. – wim Sep 14 '21 at 04:30
  • It's clear that `third_party['type']` is string (since it's added to another string) and that's the one that matters, the usage would be like `getattr(inital.constant, "command" + type_execution)`. .... annnnd you deleted the comment that I was replying to :) – wim Sep 14 '21 at 04:45
  • But it's also clear that the values that `third_party["type"]` takes on don't necessarily correspond 1:1 with an attribute, since OP is adding `_s` in some cases. Either way, I've added exactly what you're talking about in my latest edit. – ddejohn Sep 14 '21 at 04:48
  • Well yeah that's why I said to do `getattr(inital.constant, "command" + type_execution)` and not `getattr(inital.constant, "command" + third_party['type'])`. There is no harm in leaving that existing if statement in there. – wim Sep 14 '21 at 05:22