Is there a Python equivalent to Ruby symbols?

17,873

Solution 1

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.

Solution 2

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",
    )

Solution 3

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.

Solution 4

  1. No, there is no equivalent.
  2. No you can use every hashable object as dictionary key.

Solution 5

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

Share:
17,873

Related videos on Youtube

dreftymac
Author by

dreftymac

Greetings! Ask and answer. Share alike.

Updated on February 08, 2020

Comments

  • dreftymac
    dreftymac over 4 years

    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?

    • FriendFX
      FriendFX about 11 years
      Following up on your comment to this answer below: 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.
    • Alexander Bird
      Alexander Bird over 4 years
      Also, if you want a unique constant whose data type is not a string, you can also use custom classes for that
  • wuputah
    wuputah over 13 years
    +1. Fortunately for us Ruby developers, performant is not a word. (Sorry, we're just so semantic!) :D
  • Glenn Maynard
    Glenn Maynard over 13 years
    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.
  • Admin
    Admin over 13 years
    @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?
  • Admin
    Admin over 13 years
    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'}
  • Admin
    Admin over 13 years
    @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.
  • Admin
    Admin over 13 years
    @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.
  • Admin
    Admin over 13 years
    @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?
  • yantrab
    yantrab over 13 years
    @delnan, of course there is a way around this: dict(a=1,b=2,c=3).
  • aaronasterling
    aaronasterling over 13 years
    ironically, this solution does, at least initially, restrict you to having strings as the keys.
  • Admin
    Admin over 13 years
    @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.
  • Admin
    Admin over 13 years
    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.
  • Charles Roper
    Charles Roper over 10 years
    Here's a useful Q&A describing what intern does: stackoverflow.com/questions/1136826/…
  • Translunar
    Translunar over 8 years
    Great answer! Thanks for looking into this.
  • TomDotTom
    TomDotTom over 6 years
    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.
  • Tiana
    Tiana over 2 years
    @pylonicon check out DotMap; it is a dict type that lets you access keys with dot-notation instead of the ugly["quoted_string_within_square_brackets"] thing