Lexical cast from string to type
Solution 1:
I like using locate
, which works on built-in types:
>>> from pydoc import locate
>>> locate('int')
<type 'int'>
>>> t = locate('int')
>>> t('1')
1
...as well as anything it can find in the path:
>>> locate('datetime.date')
<type 'datetime.date'>
>>> d = locate('datetime.date')
>>> d(2015, 4, 23)
datetime.date(2015, 4, 23)
...including your custom types:
>>> locate('mypackage.model.base.BaseModel')
<class 'mypackage.model.base.BaseModel'>
>>> m = locate('mypackage.model.base.BaseModel')
>>> m()
<mypackage.model.base.BaseModel object at 0x1099f6c10>
Solution 2:
You're a bit confused on what you're trying to do. Types, also known as classes, are objects, like everything else in python. When you write int
in your programs, you're referencing a global variable called int
which happens to be a class. What you're trying to do is not "cast string to type", it's accessing builtin variables by name.
Once you understand that, the solution is easy to see:
def get_builtin(name):
return getattr(__builtins__, name)
If you really wanted to turn a type name into a type object, here's how you'd do it. I use deque
to do a breadth-first tree traversal without recursion.
def gettype(name):
from collections import deque
# q is short for "queue", here
q = deque([object])
while q:
t = q.popleft()
if t.__name__ == name:
return t
else:
print 'not', t
try:
# Keep looking!
q.extend(t.__subclasses__())
except TypeError:
# type.__subclasses__ needs an argument, for whatever reason.
if t is type:
continue
else:
raise
else:
raise ValueError('No such type: %r' % name)
Solution 3:
Why not just use a look-up table?
known_types = {
'int': int,
'float': float,
'str': str
# etc
}
var_type = known_types['int']