I have the following method declaration:
def method(alpha, size=10, logged_in=False, interactions=False):
if not isinstance(logged_in, bool):
logged_in = str(logged_in).lower() in ['true']
if not isinstance(interactions, bool):
interactions = str(interactions).lower() in ['true']
The if
statements are needed because, for example, interactions
would be falsely set to True
if I pass interaction="False"
as a parameter (so, I pass a String). While the above does the trick, I wonder if there is a more elegant way to achieve it (note that I have a lot of boolean parameters, beside logged_in
and interactions
, and I also have some int
and float
parameters. How could decorators be used here? Could one decorator be used for all bool
parameters, and how could I make a general one (i.e., supporting bool
, float
, int
, string
)? I found the answer to this question potentially useful, but still wanted to check if there are better ways.
You could try something like this.
def bool_fixer(func):
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str) and val.lower() in table:
kwargs[key] = table[val.lower()]
return func(*args, **kwargs)
return wrapper
@bool_fixer
def method(...):
do something
after the decorator does its magic then all of the string "true" and "false" will turn into their python bool
equivalent and you can skip all the checking in the method
function.
If you want it to cover ints
and floats
too:
import re
def converter(func):
patterns = {r"\d*": int, r"\d*?\.\d*": float}
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str):
if val.lower() in table:
kwargs[key] = table[val.lower()]
continue
for pattern in patterns:
if re.match(pattern, val):
kwargs[key] = patterns[pattern](val)
return func(*args, **kwargs)
return wrapper
or
def converter(func):
table = {"true": True, "false": False}
def wrapper(*args, **kwargs):
for key, val in kwargs.items():
if isinstance(val, str):
if val.lower() in table:
kwargs[key] = table[val.lower()]
elif val.isdigit():
kwargs[key] = int(val)
elif re.match(r"\d*?\.\d*", val):
kwargs[key] = float(val)
return func(*args, **kwargs)
return wrapper