When a function is defined in Python, the variable space is divided into global and local variables. If it is defined in a member function of a class, then there is additional member variable (self) space. So, is there a way to separate these different variable spaces if you want to do it in practice?
Reading and modifying local variables
First, let’s look at reading local variables. There are generally locals()
, vars()
and sys._getframe(0).f_code.co_varnames
, and there is also a method of sys._getframe(0).f_locals
, which is actually equivalent to locals()
and the related implementation code is as follows.
The code runs as follows.
In the case of the vars method without the specific variable name, it is the equivalent of the locals method, and both return results in dictionary format. If you execute locals or vars under a member function in a class, it comes with a variable of __main__.Obj object
, which is equivalent to all the member variables of self, and is actually part of the local variables. And if we use the method co_varnames
, then what we get is the names of all the local variables, and we can also define an additional member variable of self in the example.
|
|
As you can see, all the member variables are placed in self. And it should be noted that global variable x
is not present in the local variables since the beginning . So since we can isolate local variables, or the names of local variables, in this way, how do we go about adjusting or modifying these local variables? First of all, we need to know that the variable returned by the locals()
method is a copy, which means that even if we modify the result returned by the locals method, we can’t really change the value of the local variable itself.
In this case, the values of local variables are modified by the vars method and locals method respectively, and the final output is as follows.
First of all, we need to explain why the variable n
is not printed in this case. As mentioned earlier, the return value of vars and locals is a copy of the real variable, so whether we modify it or add it, the content will not be synchronized to the variable space, that is, the local variable n is still in an undefined state, but only exists in the dictionary of locals or vars. The final printout of z is 1, which means that the value of z is not affected by the change to the vars variable. So is there any way to modify local variables by string (without synchronizing to global variables)? The answer is yes, but the solution is very hacky, see the following example.
|
|
This case uses the Cython scheme to directly modify the contents of the data frame, and the f_locals used here are essentially locals. After some running, the output is as follows.
In this case, the local variable z has been successfully modified. However, as mentioned above, even if we modify the value of the local variable in this way, we still cannot create a new local variable with this solution. If you execute print (n)
, you will still get an error.
Reading and modifying global variables
It’s actually easier to view and modify global variables than it is to modify local variables. Let’s start with an example that shows how to see all global variables.
There are many ways to get local variables, but getting global variables is usually globals or the equivalent f_globals. the output of the above code is as follows.
|
|
With this approach we find the global variable x, while several local variables within the same function are not shown in the key of globals. And unlike the locals variables, the globals function returns a real data that is directly modifiable and takes effect globally. For example, we define or modify global variables within a function.
In this example, we can see that not only the modified x value takes effect, but also the new m is synchronized to the global variable. This makes it easier to divide global variables and local variables before assigning or modifying them uniformly.
Reading and modifying member variables
Every defined object in python has a hidden attribute __dict__
, which is a dictionary containing the names and values of all member variables. You can use __dict__
to assign values to the member variables of a class, which is very convenient. We can see what is contained in __dict__
with an example.
As we can see from the output, the __dict__
output is very pure, that is, all the member variable names and variable values. Although member variables are properties of an object, they operate very similarly to global variables globals, unlike locals which are read-only, as shown in the following example.
In this case, we modified the value of the member variable and also created a new one using __dict__
, and you can see that both of them are finally synchronized to the variable space, so that the modification of the member variable is completed.
Summary
Python itself is a flexible and convenient programming language, but convenience can often come with some risks, such as the implementation of built-in functions like exec and eval, which can lead to problems with sandbox escaping. Sometimes we need to batch operations, such as creating or modifying local, global, or member variables, which requires us to first save all variable names as strings, and then call them as variable names when needed. In this article, we introduce a series of non-exec and eval operations (not that there is no risk, also ctype and sys defined data frames are referenced) to view and define and modify the various variables needed.