3

Consider the code

a = 2
b = 3
mylist = {'a' : a, 'b' : b, 'product' : a * b}

This produces a dictionary of three fields, of which the third is calculated using the values of the first and second. I am looking for a more compact definition of mylist. I have tried (1)

mylist = {'a' : 2, 'b' : 3, 'product' : a * b}

which gives the error

NameError: name 'a' is not defined

and (2)

mylist = {'a' : 2, 'b' : 3, 'product' : mylist['a'] * mylist['b']}

which gives the error

NameError: name 'mylist' is not defined

I would like to find a shorter command of the form (1) because you do not need to need to mention the name of the dictionary. Maybe there exists something like currentdictionary['a']?

Karlo
  • 1,630
  • 4
  • 33
  • 57
  • 1
    Possible duplicate: https://stackoverflow.com/questions/42287867/how-to-set-a-dict-value-using-another-key-of-the-same-dict – jpp Jan 25 '18 at 16:21
  • 4
    https://stackoverflow.com/questions/3738381/what-do-i-do-when-i-need-a-self-referential-dictionary – Chris Jan 25 '18 at 16:24
  • 2
    You could use a `lambda` like [one the answers](https://stackoverflow.com/a/3739894/5858851) in the post @Chris linked. `mylist = {'a' : 2, 'b' : 3, 'product': lambda: mylist['a']*mylist['b']}` However, when you access the `"product"` key, you'd have to call it as a function: `mylist['product']()`. – pault Jan 25 '18 at 16:39

3 Answers3

4

I'd use something like a computed property in this case. It'll lazily evaluate the property when you need it; at call time. Much more robust than actively managing the product as a key-value pair.

class Pair(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    @property
    def product(self):
        return self.a * self.b

Sample Output:

>>> Pair(2, 3).product
6

Using a dictionary here is possible but strikes me as a shoehorned solution, (1) you'd need to contend with checking if key(s) exist on lookup and (2) also maintaining a synchronized product should a or b change.

ospahiu
  • 3,465
  • 2
  • 13
  • 24
1

You could use a function to specify the desired keys of the dictionary and use inspect to view the signature at run time:

import inspect
a = 2
b = 3
def get_list(a, b, product):
   pass

mylist = inspect.getcallargs(get_list, a, b, a*b)

Output:

{'a': 2, 'product': 6, 'b': 3}

The benefit of using a function in this case is that you can built a solution to find mylist around other potential objects in your code.

Ajax1234
  • 69,937
  • 8
  • 61
  • 102
0

I can not think of a one liner to do that.

from functools import reduce
mylist = {'a' : 2, 'b' : 3}
mylist["product"] = reduce(lambda x,y: x*y, mylist.values())
Rafael Rios
  • 564
  • 1
  • 7
  • 20