Making all variables accessible to namespace - python

Say I have a simple function:
def myfunc():
a = 4.2
b = 5.5
... many similar variables ...
I use this function one time only and I am wondering what is the easiest way to make all the variables inside the function accessible to my main name-space.
Do I have to declare global for each item? or any other suggested methods?
Thanks.

Best way, in my biased opinion, is to wrap the dictionary into a nice object where the "variables" are accessed as attributes -- the pattern I named Bunch when I introduced it many years ago, and a great example of the last item in the Zen of Python (if you don't know what that is, import this at an interpreter interactive prompt). To wit...:
class Bunch(object):
def __init__(self, d=None):
if d is not None: self.__dict__.update(d)
def myfunc():
a = 4.2
b = 5.5
...
return Bunch(locals())
x = myfunc()
print x.a, x.b
Using qualified names like x.a and x.b, rather than barenames such as a and b, is the crucial idea here: qualified names let you separate namespaces and treat them right, while barenames would make one big soup of everything and violate the Zen of Python;-). And of course there's no need to use an unwrapped dict and unsightly x['a'], x['b'] accesses!-)

If what you want is separation of your constants then put them in another module:
consts.py:
foo = 42
bar = 'quux'
main.py:
import consts
print consts.foo
print consts.bar[::-1]

I can't think of any good reason for doing this, but if you REALLY want to for some strange reason:
def myfunc():
x = 5.6
y = 7.3
# many other variables
globals().update( locals() )
This works because the globals function returns a dictionary of the global variables in your module's namespace, which you can dynamically update with the dictionary of all local variables returned by the locals function.
This is very dangerous because it will clobber everything in your global namespace, so if you already had an x or y variable, then they'll get overwritten. And as I said, I really can't think of a good reason to ever do this, so definitely think twice before resorting to this kind of trickery!

It sounds like what you want to do isn't natural because it isn't something you should generally do much.
Perhaps what you really want is to make a class and set all these things on an instance of it.
class MyState(object):
def __init__(self):
self.a = 4.2
self.b = 5.5
... many similar variables ...
Storing state on an instance of a class you create is usually very strongly preferred to mutating global state. This method also does not require any magic.

Related

Using a class as a container object for local variables as an alternative to 'nonlocal' in Python

Question
In Python, if I have a function with local variables and nested functions, I can assign these variables in the nested functions with the help of nonlocal:
def f():
x = 0
def _g():
nonlocal x
x = 1
def _h():
x = 2
_g()
_h()
print(x)
f() # 1
My issue with this solution is that if I have many local variables in f(), the use of nonlocal is verbose, and more disturbingly, it is very easy to forget nonlocal for a variable, and to create local variables in the nested functions without noticing it (what did I really mean in the h() function above, for instance?).
I have seen and used an alternative:
def f():
class state:
x = 0
def _g():
state.x = 1
def _h():
x = 2
_g()
_h()
print(state.x)
f() # 1
If uses the fact that a class in Python is actually an object too. Using 'class' that way is actually the least verbose way of creating a mutable container for local values (I believe).
I think there are two questionable aspects in this pattern:
That particular use of the 'class'-keyword might be considered as a hack.
Since the container is somewhat artificial, it is sometimes difficult to find a good name for it (I went so far as testing the use of the name 'self' for it, but that seemed even more like a hack).
Is this a good pattern? What alternatives do you usually use?
If StackOverflow is not the right forum for this question, please advise on a different forum that you think is better suited (I did read the FAQs, but what the correct forum is for this question not obvious to me).
Thanks in advance.
P.S.
For the sake of completeness, there is at least one more alternative, which feels even more like a hack:
class f:
def __init__(self):
self.x = 0
self._g()
self._h()
print(self.x)
def _g(self):
self.x = 1
def _h(self):
x = 2
f() # 1
This works because in Python, class instantiation has the same syntax as a function call.
Answer
See the accepted answer below. For a discussion about a solution when the function needs to return a value see there.
Your "last resort" alernative is of course cleaner - if you can do it in flattened methods that share an state, that is more readable code than nested functions to do the same job. "Flat is better than nested".
Other than that, you are creating a class to have a namespace. You could simply create an object to work as namespace, and it would work as a namespace - that is more usual. The only thing there is that if you simply create an instance of object itself, it can't work as namespace, because it have no __dict__, so you can't freely attribute objects for this.
That is why buried in the types module in the stdlib there is a class named SimpleNamespace exactly for this use case.
Just do:
from types import SimpleNamespace
def f():
state = SimpleNamespace()
state.x = 0
...
(but only if you don't change your mind and go for the class-based solution which is cleaner anyway).
Why not just use a dict instead of the class. This removes some of the "hackyness" and is Python 2 compatible:
def f():
state=dict(x=0)
def _g():
state["x"] = 1
def _h():
x = 2
_g()
_h()
print(state["x"])
f() # 1

Sharing global variables between classes in Python

I'm relatively new to thinking of python in terms of object-oriented programming, and it's coming relatively slowly to me.
Is it possible to pass global variables between classes with multiple functions in them? I've read extensively about them here and in other sources, but I'm still a bit confused.
My ultimate goal is to define a variable globally, assign it a value in a function of one class, and then USE it in another class's function. Is that possible? I'm building a pythonaddin for ArcMap, which requires a class for each button. I want to have a button to assign a value to a variable, and then use that variable in another class in the script.
(Before I get the flak, I know it's relatively bad form to use global variables in the first place, I'm trying to learn)
For instance, as a highly simplified example:
x = []
class A():
def func_1(self):
#populate the x variable
global x
x = 1
class B():
def func_2(self):
global x
#do stuff with x
Is this acceptable (even if not pythonic)?
Yes, it can work. Here is the modified code:
x = []
class A:
def func_1(self):
#populate the x variable
global x
x.append(1)
class B:
def func_2(self):
global x
print x
a = A()
a.func_1()
b = B()
b.func_2()
It can print the list x correctly. When it's possible, you should try to avoid global variables. You can use many other ways to pass variables between classes more safely and efficiently.
PS: Notice the parameters in the functions.
A more Pythonic solution would be to have the button objects (in their method that handles the "press" event) set an attribute or call a method of whatever object needs the information.
Yes, it is possible. Your code is almost right, just missing a couple of parenthesis in the function definitions. Other than that, it works.
Now, is that acceptable? In 99% of cases, no, it's not. There're many ways of passing variables and sharing data between classes, and using global variables is one of the worse ones, if not the worst.

Python: Using vars() to assign a string to a variable

I find it very useful to be able to create new variables during runtime and create a dictionary of the results for processing later, i.e. writing to a file:
myDict = {}
for i in range (1,10):
temp = "variable"+str(i)
vars()[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
myDict[temp] = vars(temp)
which creates the dictionary entry [result1:data1] which i can call with myDict[result1]. I have been using vars() without really understanding what I'm doing. I take it vars() returns a dictionary with the local variables(?), and
vars()[x] = y
creates a new dictionary entry of [x:y] ?
I have a script where I pass in a dictionary prepared with {input1:data1,input2:data2}, and i use this method to iterate through all the values, store all the results, and output it to a file. This bit of code is inside a function within a class, and is working.
My source of confusion is that I have read various posts on how locals() shouldn't be messed with, and how vars() is equivalent(?) to locals(), or globals()..
So my question is (at least) two-fold:
1.What exactly does vars(),or in particular, vars()[x] = y do,
2.What the scope of this dictionary is (what I need to keep in mind as I write bigger programs
3.Whether this is good programming practice.
Thanks in advance!
The pythonic way to create a sequence of variables
If you want a sequence of variables, create a sequence. Instead of trying to create independent variables like:
variable0
variable1
variable2
variable3
You should look at creating a list. This is similar to what S.Lott is suggesting (S.Lott usually has good advice), but maps more neatly onto your for loop:
sequence = []
for _ in xrange(10):
sequence.append(function_that_returns_data())
(Notice that we discard the loop variable (_). We're just trying to get 10 passes.)
Then your data will be available as:
sequence[0]
sequence[1]
sequence[2]
sequence[3]
[...]
sequence[9]
As an added bonus, you can do:
for datum in sequence:
process_data(datum)
At first, you may twitch at having your sequence start at 0. You can go through various contortions to have your actual data start at 1, but it's more pain than it's worth. I recommend just getting used to having zero-based lists. Everything is built around them, and they start to feel natural pretty quickly.
vars() and locals()
Now, to answer another part of your question. vars() (or locals()) provides low level access to variables created by python. Thus the following two lines are equivalent.
locals()['x'] = 4
x = 4
The scope of vars()['x'] is exactly the same as the scope of x. One problem with locals() (or vars()) is that it will let you put stuff in the namespace that you can't get out of the namespace by normal means. So you can do something like this: locals()[4] = 'An integer', but you can't get that back out without using locals again, because the local namespace (as with all python namespaces) is only meant to hold strings.
>>> x = 5
>>> dir()
['__builtins__', '__doc__', '__name__', 'x']
>>> locals()[4] = 'An integer'
>>> dir()
[4, '__builtins__', '__doc__', '__name__', 'x']
>>> x
5
>>> 4
4
>>> locals()[4]
'An integer'
Note that 4 does not return the same thing as locals()[4]. This can lead to some unexpected, difficult to debug problems. This is one reason to avoid using locals(). Another is that it's generally a lot of complication just to do things that python provides simpler, less error prone ways of doing (like creating a sequence of variables).
Do this instead. It's simpler.
myDict = {}
for i in range (1,10):
temp = "variable"+str(i)
myDict[temp] = myFunctionThatReturnsData() # variable1= data1, variable2 = data2,etc.
That's all you ever need to do.
The results will be myDict['variable1'] through myDict['variable9']
You rarely need vars() or locals(). Just stop using them and use ordinary variables and ordinary dictionaries. Try to avoid things you don't understand and stick to the simple, obvious stuff.
From the help for vars,
vars(...)
vars([object]) -> dictionary
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
You are using it without vars, so let's look at the help for locals()
locals(...)
locals() -> dictionary
Update and return a dictionary containing the current scope's local
variables.
So this answers you first two questions. vars() returns a dictionary to the local variables that is indexed by the name of the variable as a string. The scope is local.
I'm not sure about the third question, but it does seem like kind of a hack which isn't a good sign. I guess if you're careful about using this only in the correct scope you can get by with it.
jcdyer explains the concepts very well and Justin Peel clearly states what vars() and locals() do. But a small example always speeds up understanding.
class Bull(object):
def __init__(self):
self.x = 1
self.y = "this"
def __repr__(self):
return "Bull()"
def test1(self):
z = 5
return vars()
def test2(self):
y = "that"
return vars(self)
def test3(self):
return locals()
def test4(self):
y = 1
return locals()
if __name__ == "__main__":
b = Bull()
print b.test1()
print b.test2()
print b.test3()
print b.test4()
print vars(b).get("y")
Which results in:
{'self': Bull(), 'z': 5}
{'y': 'this', 'x': 1}
{'self': Bull()}
{'y': 1, 'self': Bull()}
this
I can answer number 3: this isn't good programming practice. I don't exactly see what you are trying to accomplish, but I am sure there is a more elegant way of doing it without using locals() (which is the same as vars() according to help(vars) in the interactive Python shell).
Using vars / locals or globals in this way is (a) poor practice and (b) doesn't work in all cases. See Dynamically set local variable for more details. Bottom line: just use dicts -- that's what they're for.
I also search for this answer at many places. The best one I see so far is:
var_list = ["Var_Name{}".format(i) for i in range(1,100)]

Why doesn't Python have static variables?

There is a questions asking how to simulate static variables in python.
Also, on the web one can find many different solutions to create static variables. (Though I haven't seen one that I like yet.)
Why doesn't Python support static variables in methods? Is this considered unpythonic or has it something to do with Python's syntax?
Edit:
I asked specifically about the why of the design decision and I haven't provided any code example because I wanted to avoid explanation to simulate static variables.
The idea behind this omission is that static variables are only useful in two situations: when you really should be using a class and when you really should be using a generator.
If you want to attach stateful information to a function, what you need is a class. A trivially simple class, perhaps, but a class nonetheless:
def foo(bar):
static my_bar # doesn't work
if not my_bar:
my_bar = bar
do_stuff(my_bar)
foo(bar)
foo()
# -- becomes ->
class Foo(object):
def __init__(self, bar):
self.bar = bar
def __call__(self):
do_stuff(self.bar)
foo = Foo(bar)
foo()
foo()
If you want your function's behavior to change each time it's called, what you need is a generator:
def foo(bar):
static my_bar # doesn't work
if not my_bar:
my_bar = bar
my_bar = my_bar * 3 % 5
return my_bar
foo(bar)
foo()
# -- becomes ->
def foogen(bar):
my_bar = bar
while True:
my_bar = my_bar * 3 % 5
yield my_bar
foo = foogen(bar)
foo.next()
foo.next()
Of course, static variables are useful for quick-and-dirty scripts where you don't want to deal with the hassle of big structures for little tasks. But there, you don't really need anything more than global — it may seem a but kludgy, but that's okay for small, one-off scripts:
def foo():
global bar
do_stuff(bar)
foo()
foo()
One alternative to a class is a function attribute:
def foo(arg):
if not hasattr(foo, 'cache'):
foo.cache = get_data_dict()
return foo.cache[arg]
While a class is probably cleaner, this technique can be useful and is nicer, in my opinion, then a global.
In Python 3, I would use a closure:
def makefoo():
x = 0
def foo():
nonlocal x
x += 1
return x
return foo
foo = makefoo()
print(foo())
print(foo())
I think most uses of local static variables is to simulate generators, that is, having some function which performs some iteration of a process, returns the result, but mantains the state for the subsequent invocation. Python handles this very elegantly using the yield command, so it seems there is not so much need for static variables.
It's a design choice.
I'm assuming Guido thinks you don't need them very often, and you never really need them: you can always just use a global variable and tell everyone to keep their greasy paws offa' your variable ;-)
For caching or memoization purposes, decorators can be used as an elegant and general solution.
The answer's pretty much the same as why nobody uses static methods (even though they exist). You have a module-level namespace that serves about the same purpose as a class would anyway.
An ill-advised alternative:
You can also use the side-effects of the definition time evaluation of function defaults:
def func(initial=0, my_static=[])
if not my_static:
my_static.append(initial)
my_static[0] += 1
return my_static[0]
print func(0), func(0), func(0)
Its really ugly and easily subverted, but works. Using global would be cleaner than this, imo.
From one of your comments: "I'd like to use them to cache things loaded from disk. I think it clutters the instance less, if I could assign them to the function"
Use a caching class then, as a class or instance attribute to your other class. That way, you can use the full feature set of classes without cluttering other things. Also, you get a reusable tool.
This shows that on SO it always pays off to state one's problem instead of asking for a specific, low level solution (e.g. for a missing language feature). That way, instead of endless debates about simulating "static" (a deprecated feature from an ancient language, in my view) someone could have given a good answer to you problem sooner.

How to maintain lists and dictionaries between function calls in Python?

I have a function. Inside that I'm maintainfing a dictionary of values.
I want that dictionary to be maintained between different function calls
Suppose the dic is :
a = {'a':1,'b':2,'c':3}
At first call,say,I changed a[a] to 100
Dict becomes a = {'a':100,'b':2,'c':3}
At another call,i changed a[b] to 200
I want that dic to be a = {'a':100,'b':200,'c':3}
But in my code a[a] doesn't remain 100.It changes to initial value 1.
I need an answer ASAP....I m already late...Please help me friends...
You might be talking about a callable object.
class MyFunction( object ):
def __init__( self ):
self.rememberThis= dict()
def __call__( self, arg1, arg2 ):
# do something
rememberThis['a'] = arg1
return someValue
myFunction= MyFunction()
From then on, use myFunction as a simple function. You can access the rememberThis dictionary using myFunction.rememberThis.
You could use a static variable:
def foo(k, v):
foo.a[k] = v
foo.a = {'a': 1, 'b': 2, 'c': 3}
foo('a', 100)
foo('b', 200)
print foo.a
Rather than forcing globals on the code base (that can be the decision of the caller) I prefer the idea of keeping the state related to an instance of the function. A class is good for this but doesn't communicate well what you are trying to accomplish and can be a bit verbose. Taking advantage of closures is, in my opinion, a lot cleaner.
def function_the_world_sees():
a = {'a':1,'b':2,'c':3}
def actual_function(arg0, arg1):
a[arg0] = arg1
return a
return actual_function
stateful_function = function_the_world_sees()
stateful_function("b", 100)
stateful_function("b", 200)
The main caution to keep in mind is that when you make assignments in "actual_function", they occur within "actual_function". This means you can't reassign a to a different variable. The work arounds I use are to put all of my variables I plan to reassign into either into a single element list per variable or a dictionary.
If 'a' is being created inside the function. It is going out of scope. Simply create it outside the function(and before the function is called). By doing this the list/hash will not be deleted after the program leaves the function.
a = {'a':1,'b':2,'c':3}
# call you funciton here
This question doesn't have an elegant answer, in my opinion. The options are callable objects, default values, and attribute hacks. Callable objects are the right answer, but they bring in a lot of structure for what would be a single "static" declaration in another language. Default values are a minor change to the code, but it's kludgy and can be confusing to a new python programmer looking at your code. I don't like them because their existence isn't hidden from anyone who might be looking at your API.
I generally go with an attribute hack. My preferred method is:
def myfunct():
if not hasattr(myfunct, 'state'): myfunct.state = list()
# access myfunct.state in the body however you want
This keeps the declaration of the state in the first line of the function where it belongs, as well as keeping myfunct as a function. The downside is you do the attribute check every time you call the function. This is almost certainly not going to be a bottleneck in most code.
You can 'cheat' using Python's behavior for default arguments. Default arguments are only evaluated once; they get reused for every call of the function.
>>> def testFunction(persistent_dict={'a': 0}):
... persistent_dict['a'] += 1
... print persistent_dict['a']
...
>>> testFunction()
1
>>> testFunction()
2
This isn't the most elegant solution; if someone calls the function and passes in a parameter it will override the default, which probably isn't what you want.
If you just want a quick and dirty way to get the results, that will work. If you're doing something more complicated it might be better to factor it out into a class like S. Lott mentioned.
EDIT: Renamed the dictionary so it wouldn't hide the builtin dict as per the comment below.
Personally, I like the idea of the global statement. It doesn't introduce a global variable but states that a local identifier actually refers to one in the global namespace.
d = dict()
l = list()
def foo(bar, baz):
global d
global l
l.append(bar, baz)
d[bar] = baz
In python 3.0 there is also a "nonlocal" statement.

Categories

Resources