Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Acessing a variable as a string in a module

Following other posts here, I have a function that prints out information about a variable based on its name. I would like to move it into a module.

#python 2.7
import numpy as np
def oshape(name):
    #output the name, type and shape/length of the input variable(s)
    #for array or list
    x=globals()[name]
    if type(x) is np.array or type(x) is np.ndarray:
        print('{:20} {:25} {}'.format(name, repr(type(x)), x.shape))
    elif type(x) is list:
        print('{:20} {:25} {}'.format(name, repr(type(x)), len(x)))
    else:
        print('{:20} {:25} X'.format(name, type(t)))

a=np.array([1,2,3])
b=[4,5,6]
oshape('a')
oshape('b')

Output:

a                    <type 'numpy.ndarray'>    (3,)
b                    <type 'list'>             3

I would like to put this function oshape() into a module so that it can be reused. However, placing in a module does not allow access to the globals from the main module. I have tried things like 'import __main__ ' and even storing the function globals() and passing it into the submodule. The problem is that globals() is one function, which specifically returns the globals of the module it is called from, not a different function for each module.

import numpy as np
import olib

a=np.array([1,2,3])
b=[4,5,6]

olib.oshape('a')
olib.oshape('b')

Gives me:

KeyError: 'a'

Extra information: The goal is to reduce redundant typing. With a slight modification (I took it out to make it simpler for the question), oshape could report on a list of variables, so I could use it like:

oshape('a', 'b', 'other_variables_i_care_about')

So solutions that require typing the variable names in twice are not really what I am looking for. Also, just passing in the variable does not allow the name to be printed. Think about using this in a long log file to show the results of computations & checking variable sizes.

like image 906
SolverWorld Avatar asked Oct 18 '22 01:10

SolverWorld


2 Answers

The actual problem you have here is a namespace problem.

You could write your method this way:

def oshape(name, x):
    # output the name, type and shape/length of the input variable(s)
    # for array or list
    if type(x) in (np.array, np.ndarray):
        print('{:20} {:25} {}'.format(name, repr(type(x)), x.shape))
    elif type(x) is list:
        print('{:20} {:25} {}'.format(name, repr(type(x)), len(x)))
    else:
        print('{:20} {:25} X'.format(name, type(x)))

and use it like this:

import numpy as np
import olib

a=np.array([1,2,3])
b=[4,5,6]

olib.oshape('a', a)
olib.oshape('b', b)

but it's looks very redundant to have the variable and its name in the arguments.

Another solution would be to give the globals() dict to the method and keep your code.

Have a look at this answer about the visibility of the global variables through modules.

like image 76
Frodon Avatar answered Oct 21 '22 05:10

Frodon


Your logic is way over complicated, you should just pass the arrays themselves as you are also already passing the variable name as a string so you are not looking up something you don't have access to. But if you wanted to make your code work exactly as is you could set an attibute on the module:

import numpy as np
import olib

a = np.array([1, 2, 3])
b = [4, 5, 6]
olib.a = a
olib.b = b
olib.oshape('a')
olib.oshape('b')

This will take any args and search the module the code is run from for the attrs:

import numpy as np
import sys
from os.path import basename
import imp

def oshape(*args):
    # output the name, type and shape/length of the input variable(s)
    # for array or list
    file_name = sys.argv[0]
    mod = basename(file_name).split(".")[0]
    if mod  not in sys.modules:
        mod = imp.load_source(mod, file_name)
        for name in args:
            x = getattr(mod, name)
            if type(x) is np.array or type(x) is np.ndarray:
                print('{:20} {:25} {}'.format(name, repr(type(x)), x.shape))
            elif type(x) is list:
                print('{:20} {:25} {}'.format(name, repr(type(x)), len(x)))
            else:
                print('{} {} X'.format(name, type(x)))

Just pass the variable name strings:

:~/$ cat t2.py 
import numpy as np
from olib import oshape

a = np.array([1, 2, 3])
b = [4, 5, 6]
c = "a str"

oshape("a", "b", "c")


:$ python t2.py 
a                    <type 'numpy.ndarray'>    (3,)
b                    <type 'list'>             3
c <type 'str'> X
like image 44
Padraic Cunningham Avatar answered Oct 21 '22 05:10

Padraic Cunningham