5

So I created a dictionary for setting difficulty level on a little game.

diff_dict = {'easy':0.2, 'medium':0.1, 'hard':0.05} # difficulty level dict

Keys are going to be the difficulty names and the values some ratios that i would use to compute the difficulty.

So I was trying to figure out how to print only the keys to the user:

print('\nHere are the 3 possible choices: ',diff_dict.keys())

this would print as:

Here are the 3 possible choices:  dict_keys(['hard', 'easy', 'medium'])

Obviously I don't want to have the dictionary name displayed so I continued to search and I did find a solution which works:

diff_keys = diff_dict.keys()
print ('\nHere are the 3 possible choices: ',list(diff_keys))

But I still want to know if there are other methods to achieve this, then why and so on. So here I go with the Qs:

  1. Can I achieve the same result without crating a new element, such as diff_keys?

  2. Why does diff_dict.keys display the dict. name? Am I doing something wrong?

  3. On a side note, how can I print keys or other elements like lists, tuples, etc without the string quotes (')?

  4. same as #3 above but the brackets ([ ])

thanks and cheerio :-)

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
Newbie
  • 87
  • 1
  • 2
  • 9

1 Answers1

14

The thing is, in Python 3 dict's method keys() does not return a list, but rather a special view object. That object has a magic __str__ method that is called on an object under the hood every time you print that object; so for view objects created by calling keys() __str__ is defined so that the resulting string includes "dict_keys".

Look for yourself:

In [1]: diff_dict = {'easy': 0.2, 'medium': 0.1, 'hard': 0.05}

In [2]: print('Here are the 3 possible choices:', diff_dict.keys())
Here are the 3 possible choices: dict_keys(['medium', 'hard', 'easy'])

In [3]: diff_dict.keys().__str__()
Out[3]: "dict_keys(['medium', 'hard', 'easy'])"

Note that 99.9% of the time you don't need to call this method directly, I'm only doing it to illustrate how things work.

Generally, when you want to print some data, you almost always want to do some string formatting. In this case, though, a simple str.join will suffice:

In [4]: print('Here are the 3 possible choices:', ', '.join(diff_dict))
Here are the 3 possible choices: medium, hard, easy

So, to answer you questions:

Can I achieve the same result without crating a new element, such as diff_keys?

An example is shown above.

Why does diff_dict.keys display the dict. name? Am I doing something wrong?

Because its __str__ method works that way. This is what you have to deal with when printing objects "directly".

how can I print keys or other elements like lists, tuples, etc without the string quotes (')?

same as #3 above but the brackets ([ ])

Print them so that their __str__ is not called. (Basically, don't print them.) Construct a string in any way you like, crafting your data into it, then print it. You can use string formatting, as well as lots of useful string methods.

Community
  • 1
  • 1
Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
  • 2
    the important point that is missing is [the difference between `__str__` and `__repr__`](http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python). dict_keys overrides `__repr__` (that is used for `__str__`). The purpose of `repr` also explains why it includes `'` for strings. – jfs Nov 28 '12 at 20:57
  • @J.F.Sebastian Frankly speaking, I deliberately left it out to not overload the answer with details, as the OP seems to be new to Python and the use case doesn't really require complete understanding of the difference between `__repr__` and `__str__` (imho). So if you don't mind, I'd prefer not to edit this into the answer. It's good to have this as a reference for "further reading", though. Thank you for the comment :) – Lev Levitsky Nov 28 '12 at 21:05
  • 1
    @J.F.Sebastian: Actually, you have to go even more in depth to really answer #4: Calling `__str__` on a `list` or `tuple` calls `__repr__` rather than `__str__` on each of its elements. But I agree with Lev that this is perfectly fine in comments rather than the answer. – abarnert Nov 28 '12 at 21:28
  • Thanks a lot for the info, works great and i learned quite a few things. Could you please try answering this as well? why does str.join(dict) return the str keys ONLY, while i have to specify join(dict.values) to get the str values, is it that is just keys by default? what if i wanted to use str.join for both str keys AND values? Cheers. – Newbie Nov 29 '12 at 21:16
  • @Newbie There's another magic method to explain this and it's called [`__iter__`](http://docs.python.org/3/reference/datamodel.html#object.__iter__). It defines what you get on each step when you iterate over the object. When you iterate over a dict, you get its keys. Take a look [here](http://docs.python.org/3/library/stdtypes.html#mapping-types-dict) and scroll down to `iter(d)`. Also as a simple experiment you can try `for k in diff_dict: print(k)`. To get both keys and values there's [`dict.items()`](http://docs.python.org/3/library/stdtypes.html#dict.items). – Lev Levitsky Nov 29 '12 at 21:36
  • @Newbie Note that `dict.items()` yields `(key, value)` tuples, so you will need to do some string formatting to get something nice in the output. Like `', '.join('{} means {}'.format(*i) for i in d.items())`. – Lev Levitsky Nov 29 '12 at 21:42
  • Thanx Mate, could you please explain in words what: "', '.join('{} means {}'.format(*i) for i in d.items())" is doing?? – Newbie Dec 01 '12 at 21:40
  • @Newbie The use of `{}` is explained in the "String formatting" page; the new thing for you is probably the use of `*`; it's called [`unpacking`](http://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists). Basically, the command creates a string using both key and value from each item, the joins the strings. – Lev Levitsky Dec 01 '12 at 21:49
  • ```print('Here are the 3 possible choices:', ','. join(diff_dict), sep="")``` ```print('Here are the 3 possible choices:' + ', '. join(diff_dict))``` should remove extra space before easy – Subham Mar 08 '21 at 14:47