Explain locals() and exactly how it works - python

Could someone please explain how this little piece of code works?
info = {}
info.update(locals())
info.pop('self', None)
info.pop('info', None)
I am assuming, and please correct me if I am wrong, but it gets all the variables in the current function and puts them in the dict and removes self and the dict it got put in, correct? Is there anything other than self and the dict I might not want going into there?
Would there be anything wrong with just JSON serializing that dict and posting it?

This probably comes from the Django template and the locals trick. The idea is to populate a number of variables inside a function, and use locals() to pass them on to a template. It saves the effort of creating a new dictionary with all those variables.
Specifically, your code creates a dictionary of all the local variables and removes self (the class object parameter) and info (the variable that was just created). All other local variables are returned.
You could then JSON serialize the data, as long as the data can be serialized. DateTime variables must be converted to a string first, for example.

The code creates a new dictionary called 'info' and assigns all of your local python variables to it. NOTE: These are pointers to the same objects in your local environment, so that if you modify a list or dictionary in info it will be changed in your environment as well (this may or may not be the desired behavior).
locals()
Update and return a dictionary representing the current local
symbol table. Free variables are returned by locals() when it is
called in function blocks, but not in class blocks.
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.
info.pop('self', None) and info.pop('info', None) will remove 'self' and 'info', respectively, from your new info dictionary. If they are not present, they return None. Note that info.pop('self') would return a KeyError if 'self' was not in the dictionary.

Related

how to use dir() as default argument within a function [duplicate]

This question already has answers here:
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Closed 5 years ago.
I can't figure out what I'm doing wrong. It seems I'm not able to use dir() as the default argument to a function's input
def print_all_vars(arg=dir()):
for i in arg:
print(i)
foo=1
If I use
print_all_vars()
gives the output
__builtins__
__cached__
__doc__
__file__
__loader__
__name__
__package__
__spec__
but
print_all_vars(dir())
outputs
__builtins__
foo
print_all_vars
So - first, what is going on -
The line containing the def statement is run only once, when the module containing the function is first imported (or on the interactive prompt) - anyway, any expressions used as default parameter values are evaluated a single time, and their resulting object is kept as the default value for that parameter.
So, your dir() call is executed, and the resulting list - a dir on the namespace of the module containing your example function is saved. (The most common related error for Python beginners is to try to put an empty list or dictionary ( [] or {}) as a paramter default: the same list or dictionary will be reused for the lifetime of the function).
That explains why you see in the output some values that won't show up if you call it with a dir from the interactive prompt, like __package__ or __spec__.
Now, your real question is:
... I am actually trying to create an analog of MATLAB's save function
that saves all existing variables to an external file that can be
recalled later –
So, even if your dir() would be lazily executed, when the function is called only, that would still fail: it would still retrieve the variable names from the module where the function is defined, not on the callers.
The coding pattern for doing that would be:
def print_all_vars(arg=None):
if arg is None:
arg = dir()
...
(And this is the most common way to enforce empty lists of dictionaries as default parameters on the function body)
But even this, or if you pass your own list of variable names explicitly to the function, you will still have just a list of strings - not Python objects that need you will want to save.
And - if you want to retrieve the variables from the caller by default, you have a problem in common with having this list of strings: you need to be able to access the namespace of the caller code, in order to either retrieve the variable names existing there, and later to retrieve their contents in order to be saved.
The way to know "who've called your function" in Python is an advanced thing, and I am not even sure it is guarantee to work across all Python implementations - but it will certainly work on the most common (cPython, Pypy, Jython) and even some considered smaller ones (such as Brython):
You call sys._getframe() to retrieve the frame object of the code currently being executed (that is the code in your function itself) - and this frame object will have a f_back attribute, which points to the frame object of the code which called your function. The frame object, on its side, has reference to the globals and locals variables of the code being run as plain dictionaries as f_globals and f_locals respectively.
You can them "save" and "restore" as you want the contents of the global variables on the caller code - but you can't update - using pure Python code - the local variables.
So, just to list by default the global variables on the caller code - you can do:
import sys
def print_all_vars(arg=None):
if arg is None:
arg = list(sys.get_frame.f_back.f_globals.keys())
print (arg)
Being able to properly saving and restoring those variables is another question - as you can see in the comments, you can use pickle to serialize a lot of Python objects - but the caller namespace will have module names (such as mathnp`, etc...) which can't be ordinarily pickled - so you will have to come with an strategy to detect, annotate the used modules, and restoring them, by using further introspection on all objects retrieved.
Anyway, experimenting with the information here should put you on the track for what you want.

Python Access object content

I wonder how to access the content of the following object with python:
<Quota: (injected_file_content_bytes, 10240)>
I already tried to access the content of my variable called myQuota with myQuota[0] and myQuota.injected_file_content_bytes. None of them worked.
Try dir(myQuota) to see what attributes the object has. Then take it from there (or edit your question to include it) and consider what you can do with it. Alternatively, there must be some documentation explaining what this object contains.
What does the built-in dir function do?
Without arguments, return the list of names in the current local
scope. With an argument, attempt to return a list of valid attributes
for that object.
You can also use __dict__
myQuota.__dict will give you the object attributes in form of key value pairs

Trouble with the scope of variables in a class?

So I'm in the process of making a class in Python that creates a network (with pybrain) using solely the numeric input it's given {just a little process to get my feet wet in Pybrain's API}.
My problem is, I'm rather unfamiliar with how scopes work in classes, and while I basically have the program set up properly, it keeps returning a keyerror.
All the variables needed to be acted upon are created in the init function; the method I'm working on for the class is trying to call upon one of the variables, declared in the init function using the vars()[] method in Python. (you can actually see a portion of the code's...rough draft here:
Matching Binary operators in Tuples to Dictionary Items
Anyways, the method is:
def constructnetwork(self):
"""constructs network using gathered data in __init__"""
if self.recurrent:
self.network = pybrain.RecurrentNetwork
#add modules/connections here
elif self.forward:
self.network = pybrain.FeedForwardNetwork
else:
self.network = pybrain.network
print vars()[self.CONNECT+str(1)]
print vars()[self.CONNECT+str(2)]
print self.network
(pardon the bad spacing, it didn't copy and paste over well.) The part that's raising the KeyError is the "print vars()[self.CONNECT+str(1)], which should retreive the value of the variable "Connection1" (self.CONNECT = 'Connection'), but calls a keyerror.
How do I get the variables to transfer over? If you need more information to help just ask, I'm trying to keep the quesiton as short as possible.
vars() returns a reference to the dictionary of local variables. If you used vars() in your __init__ (as the code in the post you linked to suggests), then you just created a local variable in that method, which isn't accessible from anywhere outside that method.
What is it that you think vars() does, and what are you trying to do? I have a hunch that what you want is getattr and setattr, or just a dictionary, and not vars.
Edit: Based on your comment, it sounds like, indeed, you shouldn't use vars. You would be better off, in __init__, doing something like:
self.connections = {}
self.connections[1] = "This is connection 1"
then in your method, do:
self.connections[1]
This is just a vague guess based on your code, though. I can't really tell what you are intending for this "connection". Do you want it to be some data associated with your object?

add a local variables to a function

is it possible to add a local varible to a function, just before calling it ? if yes how ?
EDIT:REASON
i noticed that all my views in django are using
render_to_response(template_name,locals())
now i created a middleware and i wanted to add one more local variable using the
def process_view():
method of it .so that i don't have to modify the views .
The local scope for a function does not exist until the function is called, so it's not possible to do this. You could do this for a closure, but the next person to have to maintain the code would hunt you down and kill you.
Although I also think it is pretty useless, I thought that you may enclose the function in either a 'with' statement or another function, like the code below. Of course, this approach can be accomplished directly within the function of interest. In fact, you are adding the local variable 'during' the function declaration. See if this fits your needs!
#!/usr/bin/python
def my_funct(_local):
"""My function of interest
"""
print "Local argument was %s" % str(_local)
return "Finished"
def localize(fct, local_var):
"""
"""
return fct(_local = local_var)
## Use function to 'localize' variable
localize(my_funct, local_var="LOCAL_VARIABLE")
## Same effect without supplementary function :
my_funct(_local="LOCAL_VARIABLE")
try:
print local_var
except:
print "No such global variable"
Just some thoughts :)
Cheers
So if you’re one of those lazy
programmers and you like keeping code
particularly concise, you can take
advantage of a built-in Python
function called locals(). It returns a
dictionary mapping all local variable
names to their values, where “local”
means all variables that have been
defined within the current scope.
source
It is a trick in order to not have to explicitly list all of the variables you need to pass in to the function. In this case, you need to explicitly state a variable to pass in. Therefore, you should not be using locals() in the calls you are making in your middle-ware, as the trick was not designed to be used like that.
i mangaged to do that using decorators.

Create a new variable as named from input in Python?

This is something that I've been questioning for some time. How would I create a variable at runtime as named by the value of another variable. So, for example, the code would ask the user to input a string. A variable would then be created named after that string with a default value of "default". Is this even possible?
It is possible, but it's certainly not advised. You can access the global namespace as a dict (it's a dict internally) and add entries to it.
If you were doing an interactive interpreter, say, for doing maths, or something. You would actually pass a dict to each eval() or exec that you could then re-use as it's local namespace.
As a quick, bad, example, don't do this at home:
g = globals() # get a reference to the globals dict
g[raw_input("Name Please")] = raw_input("Value Please")
print foo
Run that, it'll traceback unless you provide 'foo' to the first prompt.

Categories