21
\$\begingroup\$

Given:

k = {'MASTER_HOST': '10.178.226.196', 'MASTER_PORT': 9999}

I want to flatten into the string:

"MASTER_HOST='10.178.226.196', MASTER_PORT=9999"

This is the ugly way that I'm achieving this right now:

result = []
for i,j in k.iteritems():
 if isinstance(j, int):
 result.append('%s=%d' % (i,j))
 else:
 result.append("%s='%s'" % (i,j))
', '.join(result)

I'm sure my developer colleagues are going to chastize me for this code. Surely there is a better way.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jan 19, 2012 at 8:47
\$\endgroup\$
1
  • \$\begingroup\$ I don't think it's that bad, unless perhaps you also have Boolean values in your dict, because isinstance(False, int) returns True, so instead of flag='False', you'd get flag=0 (both of which are not optimal). \$\endgroup\$ Commented Jan 19, 2012 at 9:00

4 Answers 4

33
\$\begingroup\$

For python 3.0+ (as @Serdalis suggested)

', '.join("{!s}={!r}".format(key,val) for (key,val) in k.items())

Older versions:

', '.join("%s=%r" % (key,val) for (key,val) in k.iteritems())
answered Jan 19, 2012 at 8:50
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Close but no cigar. I don't want quotes around 9999 for MASTER_PORT in the final result. \$\endgroup\$ Commented Jan 19, 2012 at 8:53
  • 1
    \$\begingroup\$ @BonAmi You're right. I replaced the second %s with %r to achieve that \$\endgroup\$ Commented Jan 19, 2012 at 8:57
  • \$\begingroup\$ Instead of the (key,val) you could simply write item. iteritems returns tuples, and if you have multiple replacements in a string, you replace those using a tuple. You drop a second temporary variable and imo, you gain some readability. \$\endgroup\$ Commented Jan 19, 2012 at 9:31
  • \$\begingroup\$ @Elmer That's interesting you say that, because I think novice pythoners might get more readability by using (key,val), since it explains better what happens. But I guess that's a matter of taste. I do agree your way is more efficient. \$\endgroup\$ Commented Jan 19, 2012 at 9:34
  • \$\begingroup\$ I know it's a dictionary and .iteritems returns (key, val), so unless you have better variable names that warrant creating temporary variables, like (food_name, price), you can save yourself the characters. It's all about increasing your signal to noise, and (k,v) or (key, value) is mostly noise. \$\endgroup\$ Commented Sep 18, 2015 at 6:35
9
\$\begingroup\$

Dor Shemer's method is very good, however since 3.0+ came out, pythoneque? language is moving towards:

', '.join("{!s}={!r}".format(k,v) for (k,v) in k.items())

using .format instead of % () to format a string.

both will give the same result and are correct.

I used items for python 3.0+, but for python 2.x use iteritems

answered Jan 19, 2012 at 8:58
\$\endgroup\$
2
  • \$\begingroup\$ You're right. I keep thinking with python 2.6 \$\endgroup\$ Commented Jan 19, 2012 at 9:00
  • 2
    \$\begingroup\$ new syntax 3.6: f"this is a string {variable}" \$\endgroup\$ Commented Feb 5, 2017 at 20:18
2
\$\begingroup\$

If you want exactly that output format, your way is quite OK imo. Because you want your keys unquoted and your values quoted if they're strings and unquoted if they're just numbers, there is no 'easy way' I think

In general str(k) will return a string like {'MASTER_HOST': '10.178.226.196', 'MASTER_PORT': 9999}

answered Jan 19, 2012 at 8:54
\$\endgroup\$
1
\$\begingroup\$

For python 3.6+ you can use f-strings:

', '.join(f'{k}_{v}' for k, v in my_dict.items())
Stephen Rauch
4,31412 gold badges24 silver badges36 bronze badges
answered Feb 17, 2021 at 23:41
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice! Do you think you can improve the efficiency a little? \$\endgroup\$ Commented Feb 18, 2021 at 0:38

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.