77

Is there a Python equivalent to Ruby symbols?

  • If so then what is it?

  • If not then are we stuck with using strings as our keys in dictionaries only?

dreftymac
  • 27,818
  • 25
  • 108
  • 169
  • 4
    Following up on your comment to [this answer below](http://stackoverflow.com/a/3743919/897968): If you want something where you can type `d.b` instead of `d['b']`, you could just use an empty `class D(object): pass` to create an instance `d = D()` to which you can then assign your values to attributes you make up, like so `d.a=1` and `d.b=2` and of course get their values like so `print(d.a + d.b)`. Not sure if that would be slower than a plain dictionary lookup like the `d['b']` in the answer. – FriendFX Mar 15 '13 at 07:04
  • Also, if you want a unique constant whose data type is not a string, you can also use custom classes for that – Alexander Bird Sep 09 '19 at 18:42

5 Answers5

78

No, python doesn't have a symbol type.

However string literals are interned by default and other strings can be interned using the intern function. So using string literals as keys in dictionaries is not less performant than using symbols in ruby.

Alexey
  • 3,241
  • 5
  • 25
  • 40
sepp2k
  • 341,501
  • 49
  • 643
  • 658
  • 20
    +1. Fortunately for us Ruby developers, performant is not a word. (Sorry, we're just so semantic!) :D – wuputah Sep 18 '10 at 21:22
  • 11
    Thie major benefit of this is that the language has one less core syntax and builtin type. It's unnecessary complexity in the language when it can be done transparently. – Glenn Maynard Sep 18 '10 at 21:33
  • @Glenn At first I was upset to hear that Python did not have symbols and that string literals can be used as keys. The problem is that I am not happy with the fact that I will have to place quotes around all my keys. Is there a way around this? –  Sep 18 '10 at 21:43
  • 1
    @J3M 7OR3: No, of course there's no way around this. But consider: It's just one additional character, and in real code, you often use varibles instead of literal keys anyway. –  Sep 18 '10 at 21:56
  • 12
    @delnan, of course there is a way around this: dict(a=1,b=2,c=3). – Ned Batchelder Sep 18 '10 at 23:22
  • Here's a useful Q&A describing what intern does: http://stackoverflow.com/questions/1136826/what-does-python-sys-intern-do-and-when-should-it-be-used – Charles Roper Nov 12 '13 at 16:05
  • The symbol = object() is probably closer to a Ruby Symbol than the above solution as this creates a unique object. foo = intern('foo) doesn't as foo == 'foo' would still be true. – TomDotTom Jan 28 '18 at 18:11
20

As others have said, there is no symbol in Python, but strings work well.

To avoid quoting strings as keys, use the dict() constructor syntax:

d = dict(
    a = 1,
    b = 2,
    c = "Hello there",
    )
Ned Batchelder
  • 323,515
  • 67
  • 518
  • 625
  • 1
    ironically, this solution _does_, at least initially, restrict you to having strings as the keys. – aaronasterling Sep 18 '10 at 23:45
  • yeah, it is a work around but only during the assignment step. i still have to add quotes around the b in d['b'] to get its value. i guess i just remember ruby symbols being easier to type. i wish there was a module that solved this problem. i wonder if it would make the program run slower though. –  Sep 20 '10 at 13:56
13

Also for those interested: symbols in Ruby when used in a hash are very similar to empty objects in python. For example you could do:

some_var = object()

and then set a dictionary key as some_var:

some_dict = { some_var : 'some value' }

and then do a standard retrieval:

some_dict[some_var]

However, as sepp2k noted there is no performance benefit in doing this. In fact I did a quick test and noted little to no performance boost:

a, b, c, d, e = [object() for _ in range(5)]
dict_symbols = {a : 'a', b : 'b', c : 'c', d : 'd', e : 'e'}
dict_strings = {'a' : 'a', 'b' : 'b', 'c' : 'c', 'd' : 'd', 'e' : 'e'}

def run_symbols():
    for key in dict_symbols.keys():
        dict_symbols[key]

def run_strings():
    for key in dict_strings.keys():
        dict_strings[key]

Speed tested in ipython:

In [3]: %timeit run_symbols
10000000 loops, best of 3: 33.2 ns per loop

In [4]: %timeit run_strings
10000000 loops, best of 3: 28.3 ns per loop

So in my case the 'symbols' run slower! (for fun numbers, not accurate). However it is to note that there are probably memory advantages to doing it this way. If you don't care about the key type objects have a smaller footprint than strings.

import sys
sys.getsizeof('some_var') # 45
some_var = object() 
sys.getsizeof(some_var) # 0

Although that raises the question of how python treats the memory of the variable name some_var.

MartianE
  • 354
  • 6
  • 8
7
  1. No, there is no equivalent.
  2. No you can use every hashable object as dictionary key.
Philipp
  • 43,805
  • 12
  • 78
  • 104
  • Can one assign a string literal to a variable and then use that variable as a key. e.g. orange = 'orange" food_type = {orange : 'fruit', banana : 'fruit'} –  Sep 18 '10 at 21:56
  • @J3M 7OR3: Strings are hashable! As are all immutable types. Concerning the second question... Python is not Javascript - keys in dict literals are not special. They can be any expression (a variable, a literal, ...), are evaluated and the result is used as key. So yes, this works. –  Sep 18 '10 at 21:58
  • @delnan Ok. But is using a variable, instead of a string literal, as a key best practice? Do people typically do this? Or are they fine with using just string literals ( with their quotes) as keys? –  Sep 18 '10 at 22:13
  • 1
    @J3M 7OR3: Wat? Most of the time, you can't possibly know the key by the time you write the program. Of course `k = "key"; d[k] = "value"` is stupid (but not `for k in keys: d[k] = "default"`, although there are better ways), but as already said, most of the time you use runtime-values as keys. –  Sep 19 '10 at 06:47
4

Not as a first-class type but there does exist https://pypi.python.org/pypi/SymbolType.

Michael Wolf
  • 1,968
  • 2
  • 15
  • 14