16

In R, the get(s) function retrieves the value of the symbol whose name is stored in the character variable (vector) s, e.g.

X <- 10
r <- "XVI"
s <- substr(r,1,1) ## "X"
get(s)             ## 10

takes the first symbol of the Roman numeral r and translates it to its integer equivalent.

Despite spending a while poking through R-Python dictionaries and Googling various combinations of "metaprogramming", "programming on the language", "symbol", "string", etc., I haven't come up with anything. (I am a very experienced R user and a novice Python user.)

(I know the example above is a (very!) poor way to approach the problem. I'm interested in the general answer to this question, not specifically in converting Roman numerals to integers ...)

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Just so you know, if you were going to do conversion of Roman numerals, you'd probably be best off having a dictionary `r={'M':1000,'D':500,'C':100,'L':50,'X':10,'V':5,'I':1}`, and just using `r['X']`. – mbomb007 Jan 30 '15 at 22:46
  • yes, I did know that ... thanks. (Although it would also be useful to have an *ordered* analogue of a dictionary to be able to ensure iteration in value order ...) – Ben Bolker Jan 30 '15 at 22:46
  • Why do you want to do this? There are usually better ways... :) – Lily Chung Jan 31 '15 at 21:02
  • the ordered analogue of a dictionary/iteration in order, or the original symbol-referencing question? – Ben Bolker Jan 31 '15 at 21:05

2 Answers2

17

You can use locals:

s = 1
locals()['s']

EDIT:

Actually, get in R is more versatile - get('as.list') will give you back as.list. For class members, in Python, we can use getattr (here), and for built-in things like len, getattr(__builtins__, 'len') works.

zw324
  • 26,764
  • 16
  • 85
  • 118
  • This is much better than `eval()`. – L3viathan Jan 30 '15 at 22:24
  • 2
    @L3viathan: can you explain why? – Ben Bolker Jan 30 '15 at 22:24
  • 6
    `eval` will evaluate and execute any code you give it. In your case that might not make a difference, but in general it can be dangerous (with unverified/uncleaned input), it should almost always be avoided. `locals()` just returns a dictionary of local variables, which is what you want. – L3viathan Jan 30 '15 at 22:26
  • In case of regression `formula = y~ eval(s)` produces the desired result while `formula = y~ locals()['s']` does not, any idea why? – Jia Gao Mar 16 '19 at 13:21
6

Use the eval function, which evaluates a string as an expression.

X = 10
r = "XVI"
v = eval(r[0])

Important note: eval() evaluates any code that can be used in an expression, not just variables. Do not use it directly in conjunction with user input, which could risk a security vulnerability.

mbomb007
  • 3,788
  • 3
  • 39
  • 68
  • 1
    I know this works, but it's not the "right" way to do it. `eval` is potentially dangerous and should almost always be avoided. – L3viathan Jan 30 '15 at 22:25
  • @L3viathan He said he wants a general solution. It doesn't necessarily mean he's taking user input. This is one solution. – mbomb007 Jan 30 '15 at 22:26
  • A general solution to get the value of a "symbol". `locals()` will do that (or `globals()` for globals). – L3viathan Jan 30 '15 at 22:27
  • 2
    I understand/agree with the argument that `locals()` is better. This was still a useful answer for me, so I'm upvoting it (but will probably accept the `locals()` answer). – Ben Bolker Jan 30 '15 at 22:28
  • 1
    @BenBolker, but if you ever need to accept user input like `"2*2+(4*3)"` or something, that'd be harder to do with `locals()`, but yeah, it's good for your roman numeral example. In the case of a math expression as user input, I'd maybe try validating with a regular expression before eval... – mbomb007 Jan 30 '15 at 22:30