0

I'm trying to update json dynamically by set of "rule" keymap.

basically it's working for different fields but not for this specific case, the sequence_handler function - get as the required sequence by name and increment the global variable .

This updating the json as expected:


CUSTOMER_NO = 1000
SUBSCRIBER_NO = 9000

def sequence_hanlder(sequence_name):
    globals()[sequence_name] += 1  
    return globals()[sequence_name]

my_json = { "subscriber_no": "val1", "customer_no": "val2"}

key_map = {"subscriber_no": sequence_hanlder("SUBSCRIBER_NO"),
 "customer_no": sequence_hanlder("CUSTOMER_NO")
 }
#this works
my_json['subscriber_no'] = sequence_hanlde("SUBSCRIBER_NO")

I'd like to key the update values by

 key_map(<filed_name>)())

but it leads to error:

my_json['subscriber_no'] = key_map['subscriber_no']()

...
TypeError: 'int' object is not callable
AviC
  • 354
  • 1
  • 5
  • 15
  • It's not completely clear what you want. You seem to want a dictionary that returns an incrementing value each time you access a key? – Iain Shelvington Dec 24 '21 at 23:13
  • Iain Shelvington , exactly, i want to be able to assign the specific field in the json the functionality describe in the keymap , I wonder how the sequence_hanlder function should be written to avoid that error – AviC Dec 25 '21 at 08:54

1 Answers1

0

The error says true, sequence_hanlder("SUBSCRIBER_NO") indeed is int. When you Look at examples (A -> B indicates a function that takes type A as input an returns B)

def f(s: str) -> int:
    return int(s) # its function str -> int

If you write x = f("1") then of course x has type int. When you create a dict, python evaluates values instantly and only once, so {"key": f("1")} becomes {"key": 1}. To make it work your f needs to return a function:

def f(s: str) -> typing.Callable[..., int]:
    return lambda: int(s) # that function returns function!

(If you are not familiar with lambda abstraction, you can find many tutorials about them).

The easies way is to use partial and a helper function:

from functools import partial

def helper(sequence_name):
    return partial(sequence_hanlder, sequence_name)

key_map = {
    "subscriber_no": helper("SUBSCRIBER_NO"),
    "customer_no": helper("CUSTOMER_NO"),
}

Our helper returns proper function so can be used in dict values

my_json['subscriber_no'] = key_map['subscriber_no']()

If you want to play a bit, you could write your own dict with lazy values evaluation (so while accessing key, not while creating dictionary), here you can find more information.

kosciej16
  • 6,294
  • 1
  • 18
  • 29