3

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.

Gökhan Sever
  • 8,004
  • 13
  • 36
  • 38

4 Answers4

8

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!-)

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • Thanks Alex for the input. Your method is even longer than Mike's. What I am looking actually an IDL equivalent of "common" in Python. See http://idlastro.gsfc.nasa.gov/idl_html_help/COMMON.html – Gökhan Sever Apr 09 '10 at 21:37
  • 1
    @Gökhan, I'm quite familiar with Fortran (was quite the Fortran wiz back in the 80's and 90's), and with the saying that "you can code Fortran in any language", but the point of that saying is, you **shouldn't** -- whatever language you choose, you should use it properly by that language's idioms and culture. `Bunch`'s 3 (!!!) lines are reusable for a **lot** of extra cases, and give you **proper namespace separation**, which is absolutely crucial to good Python use. – Alex Martelli Apr 10 '10 at 01:27
  • I didn't know you were a Fortran guru. Times are changing fast when you are in IT I suppose. Who knows maybe you would like to sit in the same class with me and hearing the discussions made around over 50k lines of cloud modeling code written in Fortran and run on clusters. – Gökhan Sever Apr 10 '10 at 04:47
  • 1
    @Gökhan, I was parallelizing Fortran codes (to run optimally on 6-processor IBM 3090's with 6 Vector Facilities) in the latter part of my career with IBM Research, over 20 years ago -- these days I'm lucky enough to work at Google (where a thousand-servers job is a small one) _and_ to focus on Python (a vastly superior language -- which lets you reuse lower-level stuff coded in Fortran with f2py or pyfort, of course). – Alex Martelli Apr 10 '10 at 05:22
5

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]
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
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!

Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256
  • 1
    Those variables inside the function are my constants. I am collecting wide-spread common one-time declared variables in one function. I thought there should be an easy to make variables accessible to the main. Your method works fine. I will be careful about the caution. The names for the constants should be unique so I don't think I could overwrite any name, yet. Will see how the conversiton goes. – Gökhan Sever Apr 09 '10 at 21:21
  • 3
    If they're only set one time then why do they need to be in a function? – Ignacio Vazquez-Abrams Apr 09 '10 at 21:26
  • It is like collecting your apples and tangerines in a container called fruit basket. Simplifies my life. I call the function set_constants, so it is clearer. – Gökhan Sever Apr 09 '10 at 21:28
  • 2
    Then use another module for that. That's what they're for. – Ignacio Vazquez-Abrams Apr 09 '10 at 21:36
0

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.

Mike Graham
  • 73,987
  • 14
  • 101
  • 130
  • I am a lazy coder. I know classes work great for my use case, but it requires a lot my more key-stroke. Instantiating the class and accessing by class_instance.var. I will take the other approach for the time being until I got bitten somewhere else in the code. – Gökhan Sever Apr 09 '10 at 21:31
  • Number of characters in a source code file is a very silly thing to optimize for. Doubly so in Python, which aims to be somewhat verbose. **Being lazy is good**, but if you want to save yourself time and effort you should be making code that is maintainable, light on magic, readable, consistent, and idiomatic. – Mike Graham Apr 09 '10 at 22:02