Some Name
Some Name

Reputation: 9540

Parse string and assign to the same variable?

Is it an pythonic way to re-assign variables with values of different types?

I have a string of the form k1:v1,k2:v2,k3:v3, etc which comes from the command line. It is straightforward to parse it:

kvs=args.kvs
if kvs is not None:
    kvs = [(kv[0], kv[1]) for kv in [kv_str.split(':') for kv_str in kvs.split(',')]]   

Since I came to python from strictly-typed languages the approach does not look really clean to me since it is re-assigned with a different type.

Would it be considered a pythonic solution of parsing the string?

Upvotes: 2

Views: 834

Answers (2)

Kevin Welch
Kevin Welch

Reputation: 1508

Short Answer:

That is fine a way to do it. Although you can just do if kvs: since empty collection types are considered falsey in Python (if that is appropriate for your case of course).

Long Answer:

This is really just opinion in Python world unfortunately. When coming from strictly-typed languages to Python you will see people do things that are discouraged or prohibited in a stricter language.

That being said I think it is always safer to avoid mutation whenever possible and to create a new variable if the type changes. In large codebases where args are passed around with no type checking, this approach can save you a lot of time debugging in the future.

Another way you may see this written is something like this that assigns the list object to a new variable.

kvs = "k1:v1,k2:v2,k3:v3"

kv_pairs = [
    tuple(kv_str.split(':'))
    for kv_str in kvs.split(',')
] if kvs else []

EDIT: fixed the code sample I posted

Upvotes: 5

wjandrea
wjandrea

Reputation: 33179

It's not bad, but you might find it cleaner to parse it during argument parsing. For example in argparse, you can use a custom type:

import argparse

def kvs_string(kvs):
    if not kvs:
        return []  # Since str.split will return "['']"
    return [tuple(kv.split(':')) for kv in kvs.split(",")]

parser = argparse.ArgumentParser()
parser.add_argument('--kvs', type=kvs_string)

for args in [], ['--kvs', ''], ['--kvs', 'k1:v1,k2:v2,k3:v3']:
    print(parser.parse_args(args))

Output:

Namespace(kvs=None)
Namespace(kvs=[])
Namespace(kvs=[('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])

Upvotes: 2

Related Questions