2

Background: Migrating from R to Python with numpy/scipy. Trying to make a little module of useful functions. In particular, I'm trying to create a recursive element-type checker.

Question: Is it possible to get a list of the current valid types in the Python environment a function is being called in?

For example, isinstance(1,int) will return True, isinstance(1,str) will return False, but isinstance(1,asdf) will throw a NameError: name 'asdf' is not defined i.e. int and str are defined, but asdf is not. How can I get the list of types that are defined, or names present in the current Python environment, and filter them by types?

phant0m
  • 16,595
  • 5
  • 50
  • 82
whearyou
  • 358
  • 1
  • 5
  • 18

2 Answers2

2

In Python, types are themselves ordinary objects. That is, for example,

type('hello') == str
type(5) == int
type(int) == type
type(type) == type

are all True.

So to do this, look for all variables in scope that point to objects of type type.

To get all objects in scope, look at both dir() (which excludes built-in names like int) and dir(__builtins__) (the built-in names) locals() (variables defined in the current function), globals() (variables defined outside of functions in the current module), and vars(__builtins__) (the built-in names). These are all dictionaries from name => object, so combine them all and get the objects:

objs = dict(vars(__builtins__), **dict(globals(), **locals())).values()

and filter only types:

types_in_scope = [o for o in objs if isinstance(o, type)]

Note that these are just the variables in scope that point to types. It's quite possible to have a reference to an object whose type is not assigned to any variable in scope. For example:

def foo():
    class Foo:
        pass
    return Foo()
x = foo()
Community
  • 1
  • 1
Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
  • thanks but doesn't seem to work :/ print [type(o) for o in objs] returns all type str. therefore types_in_scope come back empty – whearyou Aug 05 '12 at 02:44
  • @whearyou: oops. I forgot `dict()` just returns the names, not the actual objects. Fixed in edit. – Mechanical snail Aug 05 '12 at 05:57
  • thank you, but http://stackoverflow.com/a/39858/1077083 apparently the ** is a bad idea, and doesn't work with Python 3 or JPython or non 2.x CPython. instead I did objs = __builtins__.__dict__ objs.update(globals()) objs.update(locals()) And it works! So thank you! I put up the check :) You'll want to edit your answer though for future users though... – whearyou Aug 05 '12 at 22:08
  • @whearyou: that's only if the keys are not strings. But here the keys are guaranteed to be strings since they are variable names. – Mechanical snail Aug 06 '12 at 01:57
0

Maybe you could look up the types module? Please see the documentation here: http://docs.python.org/library/types.html. And you may also get the current variables in your program, like so:

In [9]: def spam():
            x=5
            y=6

In [10]: spam.func_code.co_varnames
Out[10]: ('x', 'y')

Hope it helps and you can get started. Sorry, if I totally went off track.

  • 1
    I would +1 for `types` module but not sure why you included the hacky code to get variable names, it's not part of the question. – jamylak Aug 04 '12 at 07:16
  • Op: "how can I get the list of types that are defined, or names present in the current python environment".. I thought it might help the OP get the list of names in the current python environment. –  Aug 04 '12 at 07:17
  • 2
    names in the current environment would be `locals()` or `globals()` – jamylak Aug 04 '12 at 07:21
  • @ Amit "Starting in Python 2.2, built-in factory functions such as int() and str() are also names for the corresponding types. This is now the preferred way to access the type instead of using the types module." – whearyou Aug 04 '12 at 08:27
  • @ jamylak locals() and globals() appear not to return all names, since it doe not return int or str – whearyou Aug 04 '12 at 08:29