Python Forum
function to store in caller's context - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: General (https://python-forum.io/forum-1.html)
+--- Forum: News and Discussions (https://python-forum.io/forum-31.html)
+--- Thread: function to store in caller's context (/thread-28588.html)



function to store in caller's context - Skaperen - Jul-24-2020

i have a big block of code that sets up a couple dozen variables for later code to use. now i need to run this block 2 or 3 times. each time may or may not set individual variables. it might make sense to make the block be a function, but setting the variables doesn't happen in the caller's local name space. are there any workarounds or other ideas? this code is a project only i will use so the code doesn't need to be pythonic.


RE: function to store in caller's context - Gribouillis - Jul-24-2020

I would make an object instead of a function

class Block:
    def __init__(self, param):
        self.variable = 'spam' if param else 'eggs'
        self.another_var = 'ham'

....
# first use
b = Block(12)
func('hello', b.another_var)
if b.variable:
    make_coffee()
...
# second use
b = Block(None)
print(b.variable + b.another_variable)



RE: function to store in caller's context - Skaperen - Jul-26-2020

the caller will get about 30 different variables set by this block of code under the 2 different uses. so if done as a function it would be like side effects. in the original design, it was a block of code that sets 30 different variables. the new design needs to split up the block and run the whole thing twice. it can't just simply be put in a loop because there is a bunch of other code to do between those two runs of the big block. after both runs, all 30 variables are now set. if i make it as a function that returns locals() then i still need to get 30 items out of that dictionary and set those variables.


RE: function to store in caller's context - Gribouillis - Jul-26-2020

What is the advantage of doing something as unpythonic as updating locals() with 30 variables over the pythonic use of an instance which fields are these variables? For me, the only apparent benefit is that you can write omelette instead of b.omelette. There are probably several drawbacks that we have not yet discovered. So, why do you absolutely want do it this way? Is it your aesthetic sense?


RE: function to store in caller's context - ndc85430 - Jul-26-2020

I think if you have to use locals, besides some probably rare cases, you probably have a design problem.


RE: function to store in caller's context - Skaperen - Jul-26-2020

what is wrong with local variables?


RE: function to store in caller's context - Gribouillis - Jul-26-2020

The python documentation of locals() says this
Quote:Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
One reason I see for this is that in compiling to bytecode, python determines all the local variables at lexical level, which means that the set of local variables is not extensible once the code is compiled. This makes it a very special dictionary in the python world.

There is nothing wrong with local variables in theory, but the language doesn't define ways of updating the local dictionary. See the following example
>>> spam = "Hello"
>>> 
>>> def foo():
...     exec("spam = 'world'")
...     return spam
... 
>>> foo()
'Hello'
or this
>>> spam = "Hello"
>>> 
>>> def foo():
...     spam = 'xxxx'
...     exec("spam = 'world'", globals(), locals())
...     return spam
... 
>>> foo()
'xxxx'
Consider this an intrinsic limitation of the language due to implementation constraints.


RE: function to store in caller's context - Skaperen - Jul-27-2020

that aspect of locals() is why i haven't used it to modify them in any serious way. i have tried to modify them and it does seem to work. but there could be cases where it doesn't work, ranging from the old value remains to a segfault of the engine or undetected data corruption, and numerous cases in between such how you explained it. compiled code could be caching recently accessed or correctly modified values. since it seems to allow read/fetch access from the dictionary, that suggests to me that the compiled code is expected to store these values.