Python Sharing between Called and Called Functions

Is there a way in Python to control the scope so that the variables in the calling functions are visible inside the called functions? I want something like the following

z = 1 def a(): z = z * 2 print z def b(): z = z + 1 print z a() print z b() 

I would like to get the following output

 2 4 2 

The real solution to this problem is to simply pass z as a variable. I do not want to do this.

I have a large and complex code base with users of various levels of knowledge. They are currently trained to pass one variable, and now I have to add another. I do not trust them to pass the second variable sequentially through all the function calls, so I'm looking for an alternative that supports the interface. There is a good chance that this is not possible.

+8
scope python
source share
5 answers

I think this is what you are looking for. If you control internal functions and the variable you are looking for is already in an area somewhere in the call chain, but you do not want your users to include this variable in the call itself. You obviously do not need the global because you do not want internal assignments to affect the outer scope.

Using the inspect module, you gain access to the calling context. (But you should remember that it is somewhat fragile. You should probably use untyreaded CPython only.)

 import inspect def calling_scope_variable(name): frame = inspect.stack()[1][0] while name not in frame.f_locals: frame = frame.f_back if frame is None: return None return frame.f_locals[name] z = 1 def a(): z = calling_scope_variable('z') z = z * 2 print z def b(): z = calling_scope_variable('z') z = z + 1 print z a() print z b() 

This gives the correct answer:

 2 4 2 
+5
source share

This might be the right place for the class:

 class MyClass(object): def __init__(self, z): self.z = 1 def a(self): self.z = self.z * 2 print self.z def b(): self.z = self.z + 1 print self.z self.a() print self.z 

You can get the same effect with global variables, but I would suggest creating your own namespace (for example, with a class) and using it for your scope.

+5
source share

In general, the best solution is always just to pass values ​​around - it will be much more predictable and natural, it is easier to work and debug:

 def a(z): z = z * 2 print z def b(): global z z = z + 1 print z a(z) print z b() 

You can define a() in b() and do something like this:

 def b(): global z z = z + 1 print z def a(): z = z * 2 print z a() print z 

However, this is not entirely optimal.

+2
source share

I don’t quite understand what you are trying to achieve, but this prints 2, 4, 2:

 z = 1 def a(): global z y = z * 2 print y def b(): global z z = z + 1 print z a() print z b() 
+2
source share

It's a little ugly, but it avoids using global variables, and I tested it and it works. Using the code from the selected answer here , the getSetZ() function has a “static” variable that can be used to store the value passed to it and then retrieved when the function is called using None as a parameter. Certain limitations are that it assumes that None not a possible value for z and that you are not using threads. You just need to remember the call to getSetZ() before each call to the function in which you want the calling function z be available, and to get the value from getSetZ() and put it in a local variable in that function.

 def getSetZ(newZ): if newZ is not None: getSetZ.z = newZ else: return getSetZ.z def a(): z = getSetZ(None) z = z * 2 print z def b(): z = getSetZ(None) z = z + 1 print z getSetZ(z) a() print z getSetZ.z = 0 getSetZ(1) b() 

Hope this helps.

+1
source share

All Articles