2

Is it possible to make simple variables from dictionaries? Something like:

dct = {'key1': val1, 'key2': val2}

should be turned to the variables key1 and key2, so that

print key1
val1
print key2
val2

Why it may be important? In my case because of readability.

I'm implementing multiple design standards in my project, to design well, stuff.

To separate the design code from the physical object being calculated I use interface functions, that get some of the objects that describe the physical object, extract the data needed and return these as dictionaries to be used in the functions doing the standard-based calculation.

Using dictionaries for this makes passing arguments easy (positional arguments would be a nightmare, kwargs yields the same problem that I have now), but results unreadable code when it comes to implementing the formulae in the standard.

An example, a rather simple formula:

_ret = (d['Da'] * d['p']) / (20 * (d['K'] / d['S']) * d['v'] + d['p']) + d['c1'] + d['c2']

vs.

_ret = (Da * p) / (20 * (K / S) * v + p) + c1 + c2

Another solution would be to make a class instead of the dict, using type(). That would result in something like:

_ret = (c.Da * c.p) / (20 * (c.K / c.S) * c.v + c.p) + c.c1 + c.c2

This is better, but not by much.

To avoid the visual noise, now I simply define new variables from all key-value pairs passed from the interface function, like

Da = d['Da']
p = d['p']

etc.

This solution is surely not the best, although it leads to easy to read code - but I couldn't come up with a 'magical' one. Do you have any suggestions how to do this transformation simply?

paisanco
  • 4,098
  • 6
  • 27
  • 33
jake77
  • 1,892
  • 2
  • 15
  • 22
  • 3
    If you have a function `def f(key1, key2):` and call it `f(**dct)`, within the function you'd get the behaviour you want. Otherwise you've have to play with e.g. `locals`, which is a bad idea. – jonrsharpe Sep 26 '15 at 15:46
  • @jonrsharpe Function suggestion was the best! – Mazdak Sep 26 '15 at 15:47
  • you stated "kwargs yields the same problem that I have now" . can you explain, as previous comments mention, it seems like it is the perfect solution for your problem – DorElias Sep 26 '15 at 15:48
  • @jonsharpe, this is true - I did not know it works like this, thank you for the idea! -, but in case of many arguments (say 10+) this bloats the function definition. – jake77 Sep 26 '15 at 16:00
  • @DorElias I meant the other way where def f(**kwargs) is used - that makes the part where f is called hard to follow in case of many variables, but is no solution for my problem since **kwargs will be a dict in f. – jake77 Sep 26 '15 at 16:05
  • It does, but then refactoring related parameters into a single object is a pattern in itself. If you only needed some of the parameters locally, you could use e.g. `def f(key2, **kwargs):` to mop up the unneeded ones. – jonrsharpe Sep 26 '15 at 16:22
  • I pass only the arguments necessary for the calculation - this makes the function reusable, thus no unnecessary parameters. But then - if the aim is readability, showing all parameters in the function definition is not that bad (think highlighting unused parameters), especially if calling is kept simple. – jake77 Sep 26 '15 at 17:08

1 Answers1

-1

Method-1: Using vars()

You can use the built-in function vars() to do that.

Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute.

Without an argument, vars() acts like locals().

In [1]: dct = {'key1': 1, 'key2': 2}

In [2]: vars().update(dct) # creates variables with name as keys and value as their corresponding value of 'dct' dictionary

In [3]: key1 # access 'key1' as variable
Out[3]: 1

In [4]: key2 # access 'key2' as variable
Out[4]: 2

Method-2: Using **kwargs

Another option is to use **kwargs as suggested by @Jonrsharpe which is a cleaner approach.

We define a function some_function having arguments as the keys of the dictionary. We call this function and pass it the dictionary dct using **kwargs option. This will give us access to the keys key1 and key2 as variables inside that function.

In [1]: dct = {'key1': 1, 'key2': 2}

In [2]: def some_func(key1, key2): # define keys as function parameters
   ...:     print key1 # print value of variable 'key1'
   ...:     print key2 # print value of variable 'key2'
   ...:  

In [3]: some_func(**dct) # pass 'dct' dictionary using '**kwargs'
1 # Value of variable 'key1'
2 # Value of variable 'key2'
Community
  • 1
  • 1
Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
  • 1
    You meant `vars()[key] = value` ? – Anand S Kumar Sep 26 '15 at 16:22
  • @jonrsharpe Yes, can use that. Updated the ans. – Rahul Gupta Sep 26 '15 at 16:47
  • Did you actually *test* your use of `**kwargs`? It looks like an interpreter session, but that's not how it works. I think you're getting confused by global variables in your current session. – jonrsharpe Sep 26 '15 at 16:50
  • This solution works in the shell, but fails when my program runs. vars() is updated, but trying to access the new variables gives NameError. – jake77 Sep 26 '15 at 16:56
  • @jake77 Can you post the code which you are trying. – Rahul Gupta Sep 26 '15 at 17:02
  • This is a compilation of code lines and resulting outputs: `print d {'c1': 0, 'Da': 2000} print vars() {'d': {'c1': 0, 'Da': 2000}} vars().update(d) print vars() {'d': {'c1': 0, 'Da': 2000}, 'Da': 2000, 'c2': 1.0} print 'Da' in vars() True print vars()['Da'] 2000 print Da NameError` – jake77 Sep 26 '15 at 17:14
  • `d = {'c1': 0, 'Da': 2000}` `vars().update(d)` `print 'Da' in vars()` `print Da` I am running these 4 lines together in a sequence in a script and its working fine for me. – Rahul Gupta Sep 26 '15 at 17:31
  • Are you doing anything extra between `print vars()['Da']` and `print Da` lines? – Rahul Gupta Sep 26 '15 at 17:51
  • Nothing. Da is in vars() but is inaccessible as variable; the IDE I use also highlights as unresolved reference. – jake77 Sep 26 '15 at 18:02
  • 1
    @RahulGupta, I couldn't find out the reason why the solution using vars() doesn't work in my program. Still, I accept the answer. – jake77 Sep 30 '15 at 07:40
  • @jake77 Even i could not get why you are not able to use `vars()` in your program. Maybe you can try posting that as a separate question. Also, you can use the `kwargs` approach if there are not too many parameters. – Rahul Gupta Sep 30 '15 at 08:57