Related
In JavaScript (and Node.js and TS), when we have an object A which has an attribute B, which has an attribute C, which has an attribute D and so on, we may use it like that:
const x = A?.B?.C?.D
Is there something similar in Python?
I want x to be None if any of A, B, C, or D is None. Actually, I need x = A.B.C.D or DEFAULT_VALUE
What I do today is very verbose:
x = None
if A is not None and A.B is not None and A.B.C is not None:
x = A.B.C.D
Is there a one-line solution in Python?
I prefer an approach like this, but it is still very verbose and I repeat myself. Looking for DRY.
x = A and A.B and A.B.C and A.B.C.D or DEFAULT_VALUE
There is probably no such concise solution in Python. The most "pythonic" way would probably be to "ask for forgiveness rather than permission" (see the "EAFP" entry in the Python Glossary), i.e. to use a try-except statement that directly tries to access D (no need for intermediate checks) and that fails gracefully by providing the required DEFAULT_VALUE in the error case:
try:
x = A.B.C.D
except (NameError, AttributeError):
x = DEFAULT_VALUE
You only need the NameError for the case that A might not exist at all. If you are sure that A exists (i.e. A has been defined and holds any value including None) you can drop it from the except clause.
I would define a function that allows you get the desired behavior in just one line:
def f(x, lst, default_val=None):
for att in lst:
if hasattr(x, attr):
x = getattr(x, attr)
else:
return default_val
return x
Now you can do things like this:
X = f(A, ['B', 'C', 'D'])
As suggested in the comments, if you don't need a default value, then you can just define the function as follows:
def f(x, lst):
for att in lst:
x = getattr(x, attr, None)
return x
I think a one-liner would be very messy here tbh. If you have get available for whatever these objects are you could do something like:
b = A.get(B, None) if A else None
c = B.get(C, None) if B else None
x = C.get(D, None) if C else None
Generally Python favours more lines of code to make something explicit rather than a complex one-liner.
i have a function, m_chain, which refers to two functions bind and unit which are not defined. i want to wrap this function in some context which provides definitions for these functions - you can think of them as interfaces for which i want to dynamically provide an implementation.
def m_chain(*fns):
"""what this function does is not relevant to the question"""
def m_chain_link(chain_expr, step):
return lambda v: bind(chain_expr(v), step)
return reduce(m_chain_link, fns, unit)
In Clojure, this is done with macros. what are some elegant ways of doing this in python? i have considered:
polymorphism: turn m_chain into a method referring to self.bind and self.unit, whose implementations are provided by a subclass
implementing the with interface so i can modify the environment map and then clean up when i'm done
changing the signature of m_chain to accept unit and bind as arguments
requiring usage of m_chain be wrapped by a decorator which will do something or other - not sure if this even makes sense
ideally, i do not want to modify m_chain at all, i want to use the definition as is, and all of the above options require changing the definition. This is sort of important because there are other m_* functions which refer to additional functions to be provided at runtime.
How do i best structure this so i can nicely pass in implementations of bind and unit? its important that the final usage of m_chain be really easy to use, despite the complex implementation.
edit: here's another approach which works, which is ugly as all hell because it requires m_chain be curried to a function of no args. but this is a minimum working example.
def domonad(monad, cmf):
bind = monad['bind']; unit = monad['unit']
return cmf()
identity_m = {
'bind':lambda v,f:f(v),
'unit':lambda v:v
}
maybe_m = {
'bind':lambda v,f:f(v) if v else None,
'unit':lambda v:v
}
>>> domonad(identity_m, lambda: m_chain(lambda x: 2*x, lambda x:2*x)(2))
8
>>> domonad(maybe_m, lambda: m_chain(lambda x: None, lambda x:2*x)(2))
None
In Python, you can write all the code you want that refers to stuff that doesn't exist; to be specific, you can write code that refers to names that do not have values bound to them. And you can compile that code. The only problem will happen at run time, if the names still don't have values bound to them.
Here is a code example you can run, tested under Python 2 and Python 3.
def my_func(a, b):
return foo(a) + bar(b)
try:
my_func(1, 2)
except NameError:
print("didn't work") # name "foo" not bound
# bind name "foo" as a function
def foo(a):
return a**2
# bind name "bar" as a function
def bar(b):
return b * 3
print(my_func(1, 2)) # prints 7
If you don't want the names to be just bound in the local name space, but you want to be able to fine-tune them per function, I think the best practice in Python would be to use named arguments. You could always close over the function arguments and return a new function object like so:
def my_func_factory(foo, bar):
def my_func(a, b):
return foo(a) + bar(b)
return my_func
my_func0 = my_func_factory(lambda x: 2*x, lambda x:2*x)
print(my_func0(1, 2)) # prints 6
EDIT: Here is your example, modified using the above idea.
def domonad(monad, *cmf):
def m_chain(fns, bind=monad['bind'], unit=monad['unit']):
"""what this function does is not relevant to the question"""
def m_chain_link(chain_expr, step):
return lambda v: bind(chain_expr(v), step)
return reduce(m_chain_link, fns, unit)
return m_chain(cmf)
identity_m = {
'bind':lambda v,f:f(v),
'unit':lambda v:v
}
maybe_m = {
'bind':lambda v,f:f(v) if v else None,
'unit':lambda v:v
}
print(domonad(identity_m, lambda x: 2*x, lambda x:2*x)(2)) # prints 8
print(domonad(maybe_m, lambda x: None, lambda x:2*x)(2)) # prints None
Please let me know how this would work for you.
EDIT: Okay, one more version after your comment. You could write arbitrary m_ functions following this pattern: they check kwargs for a key "monad". This must be set as a named argument; there is no way to pass it as a positional argument, because of the *fns argument which collects all arguments into a list. I provided default values for bind() and unit() in case they are not defined in the monad, or the monad is not provided; those probably don't do what you want, so replace them with something better.
def m_chain(*fns, **kwargs):
"""what this function does is not relevant to the question"""
def bind(v, f): # default bind if not in monad
return f(v),
def unit(v): # default unit if not in monad
return v
if "monad" in kwargs:
monad = kwargs["monad"]
bind = monad.get("bind", bind)
unit = monad.get("unit", unit)
def m_chain_link(chain_expr, step):
return lambda v: bind(chain_expr(v), step)
return reduce(m_chain_link, fns, unit)
def domonad(fn, *fns, **kwargs):
return fn(*fns, **kwargs)
identity_m = {
'bind':lambda v,f:f(v),
'unit':lambda v:v
}
maybe_m = {
'bind':lambda v,f:f(v) if v else None,
'unit':lambda v:v
}
print(domonad(m_chain, lambda x: 2*x, lambda x:2*x, monad=identity_m)(2))
print(domonad(m_chain, lambda x: None, lambda x:2*x, monad=maybe_m)(2))
Okay, here is my final answer to this question.
You need to be able to rebind some functions at least some of the time. Your hack, backing up the .__globals__ value and pasting in new values, is ugly: slow, non-thread-safe, and specific to CPython. I have thought about this, and there is no Pythonic solution that works this way.
In Python, you can rebind any function, but you have to do it explicitly, and some functions are not a good idea to rebind. For example, I love the builtins all() and any(), and I think it would be scary if you could stealthily rebind them and it would not be obvious.
You want some functions to be rebindable, and I don't think you need them all to be rebindable. So it would make perfect sense to mark the rebindable functions in some way. The obvious and Pythonic way to do this is to make them method functions of a class we can call Monad. You can use the standard variable name m for instances of Monad, and then when someone tries to read and understand their code, they will know that a function with a name like m.unit() is potentially rebindable via some other Monad instance being passed in.
It will be pure Python, and completely portable, if you obey these rules:
All functions must be bound in the monad. If you refer to
m.bind() then "bind" must appear in the .__dict__ of the
instance of Monad.
Functions using Monad must take a named
argument m=, or for functions that will use the *args feature,
must take a **kwargs argument and check it for a key named "m".
Here is an example of what I have in mind.
class Monad(object):
def __init__(self, *args, **kwargs):
# init from each arg. Try three things:
# 0) if it has a ".__dict__" attribute, update from that.
# 1) if it looks like a key/value tuple, insert value for key.
# 2) else, just see if the whole thing is a dict or similar.
# Other instances of class Monad() will be handled by (0)
for x in args:
if hasattr("__dict__", x):
self.__dict__.update(x.__dict__)
else:
try:
key, value = x
self.__dict__[key] = value
except TypeError:
self.__dict__.update(x)
self.__dict__.update(kwargs)
def __identity(x):
return x
def __callt(v, f):
return f(v)
def __callt_maybe(v, f):
if v:
return f(v)
else:
return None
m_identity = Monad(bind=__callt, unit=__identity)
m_maybe = Monad(bind=__callt_maybe, unit=__identity)
def m_chain(*fns, **kwargs):
"""what this function does is not relevant to the question"""
m = kwargs.get("m", m_identity)
def m_chain_link(chain_expr, step):
return lambda v: m.bind(chain_expr(v), step)
return reduce(m_chain_link, fns, m.unit)
print(m_chain(lambda x: 2*x, lambda x:2*x, m=m_identity)(2)) # prints 8
print(m_chain(lambda x: None, lambda x:2*x, m=m_maybe)(2)) # prints None
The above is clean, Pythonic, and should run just as well under IronPython, Jython, or PyPy as it does under CPython. Inside m_chain(), the expression m = kwargs.get("m", m_identity) tries to read out a specified monad argument; if one is not found, the monad is set to m_identity.
But, you might want more. You might want the Monad class to support only optionally overriding a function name; and you might be willing to stick with just CPython. Here is a trickier version of the above. In this version, when the expression m.some_name() is evaluated, if the Monad instance m does not have the name some_name bound in its .__dict__, it will look up some_name in the locals of the caller, and in the globals().
In this case, the expression m.some_name() means "m can override some_name but doesn't have to; some_name might not be in m, in which case some_name will be looked up as if it were not prefixed by m.". The magic is in the function .__getattr__(), which uses sys._getframe() to peek at the locals of the caller. .__getattr__() is only called when the local lookup fails, so we know that the Monad instance doesn't have name bound in .__dict__; so look at the locals belonging to the caller, using sys._getframe(1).f_locals; failing that, look in globals(). Just insert this into the class definition of Monad in the source code above.
def __getattr__(self, name):
# if __getattr__() is being called, locals() were already checked
d = sys._getframe(1).f_locals
if name in d:
return d[name]
d = globals()
if name in d:
return d[name]
mesg = "name '%s' not found in monad, locals, or globals" % name
raise NameError, mesg
here is how i ended up doing it. no idea if this is a good idea. but it lets me write my m_* functions totally independent of the implementation of unit/bind, and also totally independent of any implementation details of the way monads are done in python. the right things are just there in lexical scope.
class monad:
"""Effectively, put the monad definition in lexical scope.
Can't modify the execution environment `globals()` directly, because
after globals().clear() you can't do anything.
"""
def __init__(self, monad):
self.monad = monad
self.oldglobals = {}
def __enter__(self):
for k in self.monad:
if k in globals(): self.oldglobals[k]=globals()[k]
globals()[k]=self.monad[k]
def __exit__(self, type, value, traceback):
"""careful to distinguish between None and undefined.
remove the values we added, then restore the old value only
if it ever existed"""
for k in self.monad: del globals()[k]
for k in self.oldglobals: globals()[k]=self.oldglobals[k]
def m_chain(*fns):
"""returns a function of one argument which performs the monadic
composition of fns."""
def m_chain_link(chain_expr, step):
return lambda v: bind(chain_expr(v), step)
return reduce(m_chain_link, fns, unit)
identity_m = {
'bind':lambda v,f:f(v),
'unit':lambda v:v
}
with monad(identity_m):
assert m_chain(lambda x:2*x, lambda x:2*x)(2) == 8
maybe_m = {
'bind':lambda v,f:f(v) if v else None,
'unit':lambda v:v
}
with monad(maybe_m):
assert m_chain(lambda x:2*x, lambda x:2*x)(2) == 8
assert m_chain(lambda x:None, lambda x:2*x)(2) == None
error_m = {
'bind':lambda mv, mf: mf(mv[0]) if mv[0] else mv,
'unit':lambda v: (v, None)
}
with monad(error_m):
success = lambda val: unit(val)
failure = lambda err: (None, err)
assert m_chain(lambda x:success(2*x), lambda x:success(2*x))(2) == (8, None)
assert m_chain(lambda x:failure("error"), lambda x:success(2*x))(2) == (None, "error")
assert m_chain(lambda x:success(2*x), lambda x:failure("error"))(2) == (None, "error")
from itertools import chain
def flatten(listOfLists):
"Flatten one level of nesting"
return list(chain.from_iterable(listOfLists))
list_m = {
'unit': lambda v: [v],
'bind': lambda mv, mf: flatten(map(mf, mv))
}
def chessboard():
ranks = list("abcdefgh")
files = list("12345678")
with monad(list_m):
return bind(ranks, lambda rank:
bind(files, lambda file:
unit((rank, file))))
assert len(chessboard()) == 64
assert chessboard()[:3] == [('a', '1'), ('a', '2'), ('a', '3')]
Python is already late bound. There's no need to do any work here:
def m_chain(*args):
return bind(args[0])
sourcemodulename = 'foo'
sourcemodule = __import__(sourcemodulename)
bind = sourcemodule.bind
print m_chain(3)
I would like to do the following:
print "CC =",CC
but as a function so that i only have to write the variable CC once. I can't work out how to do this in a function as it always evaluates CC as a floating point number (which it is).... Is there a way to accept the input to a function as both a string and floating point number?
I tried this:
def printme(a):
b='%s' % a
print b
return b
but of course it only prints the value of a, not its name.
You could use the inspect module (see also this SO question):
def printme(x):
import inspect
f = inspect.currentframe()
val = f.f_back.f_locals[x]
print x, '=', val
CC = 234.234
printme('CC') # <- write variable name only once
# prints: CC = 234.234
Perhaps a dictionary is a better approach to the problem. Assuming you have several name-value pairs that you want to use, you can put them in a dict:
params = {"CC": 1.2345, "ID": "Yo!", "foo": "bar"}
Then, for example, you could print all the names and values nicely formatted like this:
for key in params:
print "{0} = {1}".format(key, params[key])
But since it is still unclear why you are trying to do this, it's hard to tell whether this is the right way.
I think this is your required solution:
def printme(x):
keys_list = [key for key, value in globals().iteritems() if value == x]
print keys_list
for key in keys_list:
if id(globals()[key]) == id(x):
result = "%s = %s" %(key, x)
print result
break
return result
for example if you declare a variable:
>>> c=55.6
then result of printme(c) will be
>>> 'c = 55.6'
Note: This solution is based on globally unique id matching.
Not exactly what you want, but easy to do:
def printme(**kwargs):
for key, value in kwargs.items():
print '%s=%s' % (key, value)
return value
In [13]: printme(CC=1.23, DD=2.22)
CC=1.23
DD=2.22
Out[13]: 1.23
If I understand you correctly you want something like this?
def f(a):
print('{0}: = {1}'.format(locals().keys()[0], a))
Update:
I am aware that the example doesn't make a lot of sense, as it's basically the same as:
def f(a):
print('a: {0}'.format(a))
I merely wanted to point the OP to locals() as I didn't quite understand what he's trying to accomplish.
I guess this is more what he's looking for:
def f(**kwargs):
for k in kwargs.keys():
print('{0}: {1}'.format(k, kwargs[k]))
f(a=1, b=2)
If I understand you correctly you want a shorthand for printing a variable name and its value in the current scope? This is in general impossible without using the interpreters trace function or sys._getframe, which should in general only be used if you know what you're doing. The reason for this is that the print function has no other way of getting the locals from the calling scope:
def a():
x = 1
magic_print("x") #will not work without accessing the current frame
What you CAN do without these is explicitly pass the locals to a function like this:
def printNameAndValue(varname, values):
print("%s=%s" % (varname, values[varname]))
def a():
x = 1
printNameAndValue("x", locals()) #prints 'x=1'
EDIT:
See the answer by catchemifyoutry for a solution using the inspect module (which internally uses sys._getframe). For completeness a solution using the trace function directly - useful if you're using python 2.0 and inspect isn't available ;)
from sys import settrace
__v = {} #global dictionary that holds the variables
def __trace(frame, event, arg):
""" a trace function saving the locals on every function call """
global __v
if not event == "call":
return __trace
__v.update(frame.f_back.f_locals)
def enableTrace(f):
""" a wrapper decorator setting and removing the trace """
def _f(*a, **kwa):
settrace(__trace)
try:
f(*a, **kwa)
finally:
settrace(None)
return _f
def printv(vname):
""" the function doing the printing """
global __v
print "%s=%s" % (vname, __v[vname])
Save it in a module and use like this:
from modulenamehere import enableTrace, printv
#enableTrace
def somefunction():
x = 1
[...]
printv("x")
used a global variable to achieve this,func.__globals__.keys() contains all the variables passed to func, so I filtered out the name startin with __ and stored them in a list.
with every call to func() the func.__globals__.keys() gets updated with the new variable name,so compare the new varn with the older glo results in the new variable that was just added.
glo=[]
def func(x):
global glo
varn=[x for x in func.__globals__.keys() if not x.startswith('__') and x!=func.__name__]
new=list(set(varn)^set(glo))
print("{0}={1}".format(new[0],x))
glo=varn[:]
output:
>>> a=10
>>> func(a)
a=10
>>> b=20
>>> func(20)
b=20
>>> foo='cat'
>>> func(foo)
foo=cat
>>> bar=1000
>>> func(bar)
bar=1000
I'm sure there is a term for what I'm looking for, or if there's not, there is a very good reason what I'm trying to do is in fact silly.
But anyway. I'm wondering whether there is a (quasi) built-in way of finding a certain class instance that has a property set to a certain value.
An example:
class Klass(object):
def __init__(self, value):
self.value = value
def square_value(self):
return self.value * self.value
>>> a = Klass(1)
>>> b = Klass(2)
>>> instance = find_instance([a, b], value=1)
>>> instance.square_value()
1
>>> instance = find_instance([a, b], value=2)
>>> instance.square_value()
4
I know that I could write a function that loops through all Klass instances, and returns the ones with the requested values. On the other hand, this functionality feels as if it should exist within Python already, and if it's not, that there must be a very good reasons why it's not. In other words, that what I'm trying to do here can be done in a much better way.
(And of course, I'm not looking for a way to square a value. The above is just an example of the construct I'm trying to look for).
Use filter:
filter(lambda obj: obj.value == 1, [a, b])
Filter will return a list of objects which meet the requirement you specify. Docs: http://docs.python.org/library/functions.html#filter
Bascially, filter(fn, list) iterates over list, and applies fn to each item. It collects all of the items for which fn returns true, puts then into a list, and returns them.
NB: filter will always return a list, even if there is only one object which matches. So if you only wanted to return the first instance which matches, you'd have to to something like:
def find_instance(fn, objs):
all_matches = filter(fn, objs)
if len(all_matches) == 0:
return False # no matches
else:
return all_matches[0]
or, better yet,
def find_instance(fn, objs):
all_matches = filter(fn, objs)
return len(all_matches) > 0 and all_matches[0] # uses the fact that 'and' returns its second argument if its first argument evaluates to True.
Then, you would call this function like this:
instance = find_instance(lambda x: x.value == 1, [a, b])
and then instance would be a.
A more efficient version of Ord's answer, if you are looking for just one matching instance, would be
def find_instance(fn, objs):
all_matches = (o for o in objs if fn(objs))
return next(all_matches, None)
instance = find_instance(lambda x: x.value == 1, [a, b])
This will stop the search as soon as you find the first match (good if your test function is expensive or your list is large), or None if there aren't any matches.
Note that the next function is new in Python 2.6; in an older version, I think you have to do
try:
return all_matches.next()
except StopIteration:
return None
Of course, if you're just doing this once, you could do it as a one-liner:
instance = next((o for o in [a, b] if o.value == 1), None)
The latter has the advantage of not doing a bunch of function calls and so might be slightly faster, though the difference will probably be trivial.
Background:
I mostly run python scripts from the command line in pipelines and so my arguments are always strings that need to be type casted to the appropriate type. I make a lot of little scripts each day and type casting each parameter for every script takes more time than it should.
Question:
Is there a canonical way to automatically type cast parameters for a function?
My Way:
I've developed a decorator to do what I want if there isn't a better way. The decorator is the autocast fxn below. The decorated fxn is fxn2 in the example. Note that at the end of the code block I passed 1 and 2 as strings and if you run the script it will automatically add them. Is this a good way to do this?
def estimateType(var):
#first test bools
if var == 'True':
return True
elif var == 'False':
return False
else:
#int
try:
return int(var)
except ValueError:
pass
#float
try:
return float(var)
except ValueError:
pass
#string
try:
return str(var)
except ValueError:
raise NameError('Something Messed Up Autocasting var %s (%s)'
% (var, type(var)))
def autocast(dFxn):
'''Still need to figure out if you pass a variable with kw args!!!
I guess I can just pass the dictionary to the fxn **args?'''
def wrapped(*c, **d):
print c, d
t = [estimateType(x) for x in c]
return dFxn(*t)
return wrapped
#autocast
def fxn2(one, two):
print one + two
fxn2('1', '2')
EDIT: For anyone that comes here and wants the updated and concise working version go here:
https://github.com/sequenceGeek/cgAutoCast
And here is also quick working version based on above:
def boolify(s):
if s == 'True' or s == 'true':
return True
if s == 'False' or s == 'false':
return False
raise ValueError('Not Boolean Value!')
def estimateType(var):
'''guesses the str representation of the variables type'''
var = str(var) #important if the parameters aren't strings...
for caster in (boolify, int, float):
try:
return caster(var)
except ValueError:
pass
return var
def autocast(dFxn):
def wrapped(*c, **d):
cp = [estimateType(x) for x in c]
dp = dict( (i, estimateType(j)) for (i,j) in d.items())
return dFxn(*cp, **dp)
return wrapped
######usage######
#autocast
def randomFunction(firstVar, secondVar):
print firstVar + secondVar
randomFunction('1', '2')
If you want to auto-convert values:
def boolify(s):
if s == 'True':
return True
if s == 'False':
return False
raise ValueError("huh?")
def autoconvert(s):
for fn in (boolify, int, float):
try:
return fn(s)
except ValueError:
pass
return s
You can adjust boolify to accept other boolean values if you like.
You could just use plain eval to input string if you trust the source:
>>> eval("3.2", {}, {})
3.2
>>> eval("True", {}, {})
True
But if you don't trust the source, you could use literal_eval from ast module.
>>> ast.literal_eval("'hi'")
'hi'
>>> ast.literal_eval("(5, 3, ['a', 'b'])")
(5, 3, ['a', 'b'])
Edit:
As Ned Batchelder's comment, it won't accept non-quoted strings, so I added a workaround, also an example about autocaste decorator with keyword arguments.
import ast
def my_eval(s):
try:
return ast.literal_eval(s)
except ValueError: #maybe it's a string, eval failed, return anyway
return s #thanks gnibbler
def autocaste(func):
def wrapped(*c, **d):
cp = [my_eval(x) for x in c]
dp = {i: my_eval(j) for i,j in d.items()} #for Python 2.6+
#you can use dict((i, my_eval(j)) for i,j in d.items()) for older versions
return func(*cp, **dp)
return wrapped
#autocaste
def f(a, b):
return a + b
print(f("3.4", "1")) # 4.4
print(f("s", "sd")) # ssd
print(my_eval("True")) # True
print(my_eval("None")) # None
print(my_eval("[1, 2, (3, 4)]")) # [1, 2, (3, 4)]
I'd imagine you can make a type signature system with a function decorator, much like you have, only one that takes arguments. For example:
#signature(int, str, int)
func(x, y, z):
...
Such a decorator can be built rather easily. Something like this (EDIT -- works!):
def signature(*args, **kwargs):
def decorator(fn):
def wrapped(*fn_args, **fn_kwargs):
new_args = [t(raw) for t, raw in zip(args, fn_args)]
new_kwargs = dict([(k, kwargs[k](v)) for k, v in fn_kwargs.items()])
return fn(*new_args, **new_kwargs)
return wrapped
return decorator
And just like that, you can now imbue functions with type signatures!
#signature(int, int)
def foo(x, y):
print type(x)
print type(y)
print x+y
>>> foo('3','4')
<type: 'int'>
<type: 'int'>
7
Basically, this is an type-explicit version of #utdemir's method.
If you're parsing arguments from the command line, you should use the argparse module (if you're using Python 2.7).
Each argument can have an expected type so knowing what to do with it should be relatively straightforward. You can even define your own types.
...quite often the command-line string should instead be interpreted as another type, like a float or int. The type keyword argument of add_argument() allows any necessary type-checking and type conversions to be performed. Common built-in types and functions can be used directly as the value of the type argument:
parser = argparse.ArgumentParser()
parser.add_argument('foo', type=int)
parser.add_argument('bar', type=file)
parser.parse_args('2 temp.txt'.split())
>>> Namespace(bar=<open file 'temp.txt', mode 'r' at 0x...>, foo=2)
There are couple of problems in your snippet.
#first test bools
if var == 'True':
return True
elif var == 'False':
return False
This would always check for True because you are testing against the strings 'True' and 'False'.
There is not an automatic coercion of types in python. Your arguments when you receive via *args and **kwargs can be anything. First will look for list of values (each of which can be any datatype, primitive and complex) and second will look for a mapping (with any valid mapping possible). So if you write a decorator, you will end up with a good list of error checks.
Normally, if you wish to send in str, just when the function is invoked, typecast it to string via (str) and send it.
I know I arrived late at this game, but how about eval?
def my_cast(a):
try:
return eval(a)
except:
return a
or alternatively (and more safely):
from ast import literal_eval
def mycast(a):
try:
return literal_eval(a)
except:
return a