0

How can I write this code so it works for every type given?

def set_val_type(val, val_type):
    if val_type == 'bool':
        return bool(val)
    elif val_type == 'int':
        return int(val)
Koby 27
  • 1,049
  • 1
  • 8
  • 17

3 Answers3

0

You can do something like:

def set_val_type(val, val_type):
    return eval(val_type + '({})'.format(val))

As much as this seems to be what you are looking for, using eval is not recommended. It seems like an XY problem as commented before by @pault

Felipe Gonzalez
  • 343
  • 1
  • 6
  • 2
    [Why is using `eval` a bad practice](https://stackoverflow.com/q/1832940/5858851)? – pault Jan 07 '19 at 20:24
  • 1
    I agree, it's probably an XY problem as you commented before, just posted it because it seemed to be exactly what Koby 27 was looking for. – Felipe Gonzalez Jan 07 '19 at 20:27
  • you may want to also add the comment as a part of your answer to make it more well rounded. For Koby's sake and others like him who look up this question later. – Paritosh Singh Jan 07 '19 at 20:30
0

You can create a dictionary of all the types you need to process.

def set_val_type(val, val_type):
    funcs = {'int': int, 'bool': bool}
    return funcs[val_type](val)
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • A `funcs.get(val_type)(val)` might work more favorably especially if we are uncertain of the input to give it a little extra handling. Though I'm not sure what to put in place of the default. – r.ook Jan 07 '19 at 20:32
  • @Idlehands: [EAFP](https://stackoverflow.com/q/11360858/5987). – Mark Ransom Jan 07 '19 at 20:33
  • I understand that concept in Python, but thanks for sharing it. I'm just not sure how a `KeyError` might be more helpful, unless the whole `set_val_type` is expected to be wrapped in a `try` block. Though I must say the nature of OP's question is very... questionable already so I shall hold my tongue. – r.ook Jan 07 '19 at 20:37
  • @Idlehands I admit my reply was a bit short and cryptic. What I really meant was that raising an exception is a totally appropriate thing to do when given invalid input, and I don't think the type of the exception matters much. – Mark Ransom Jan 07 '19 at 21:14
0

To avoid using eval, and presuming you are only using builtin types, you can use a getattr() on the builtins module (if you want to make sure you don't call any functions, you can perform an isinstance(user_provided_type_here, type) before.

To allow any type in global scope, use globals()[user_provided_type_name]

Complete example:

import builtins

def set_val_type(val, val_type);
    user_type = getattr(builtins, val_type)  # possibly replace with globals()[val_type]
    if not isinstance(user_type, type):
        raise TypeError(f'{user_type} is no a type.')
    return user_type(val)

Why not to use eval() (with untrusted user input):

def set_val_type(val, val_type):
    return eval(val_type + '({})'.format(val))

evil_val_type = 'bool'
evil_val = 'exec("import os\\nos.chdir(os.path.sep)\\nprint(os.getcwd())")'

print(set_val_type(evil_val, evil_val_name))
'False'  # yes, this actually works error-free

With this level of access, one is just a subprocess.Popen / os.system from very bad news.
That said, if your user input is trusted, using eval() is not less problematic.

user24343
  • 892
  • 10
  • 19