Как безопасно оценивать индексы списков?

#python #list #indexing #eval #abstract-syntax-tree

Вопрос:

Я пытаюсь оценить некоторые выражения Python, такие как [1, 2, 3][1] . Я не могу использовать eval('[1, 2, 3][1]') , потому что каждый раз, когда я это делаю, котенок может умереть. Более безопасный способ-использовать ast.literal_eval('[1, 2, 3][1]') , однако он вызывает ошибку значения:

 ValueError: malformed node or string ...  

Что можно сделать для того, чтобы это сработало? Заранее спасибо.

Комментарии:

1. Когда вы говорите «некоторые выражения Python, такие как [1, 2, 3][1]», что это включает в себя? Если это конкретно «литерал списка, за которым следует индекс в квадратных скобках», то вы можете разбить его на части, оценить их с помощью literal_eval, а затем объединить их в своей собственной логике. Если это более общее, чем это, пожалуйста, опишите.

2. Да, это литерал списка, за которым следует индекс в квадратных скобках, команда, которая работает с использованием eval([1, 2, 3][1]) . Как я могу разбить его на части?

Ответ №1:

Возможно, есть какой-то лучший способ, но если формат такой, как вы описываете (литерал списка, за которым следует литерал индекса в квадратных скобках), то вы можете разделить его на части, оценить их по отдельности, а затем объединить их в своей логике.

 import re from ast import literal_eval string = '[1, 2, 3][1]' m = re.match(r'^([. ])[(. )]


Комментарии:

1. А, понял. Это похоже на попытку разработать свой собственный способ компиляции этого кода. Надеюсь, в будущих версиях Python будут лучшие варианты, я надеюсь.

Ответ №2:

Если это так же просто, как выбрать целое число из списка, вы можете проанализировать его самостоятельно.

 s = "[1, 12, 30][-1]"  def foo(s):  arr = []  curr = ""  for c in s:  if c.isdigit() or c in ["-"]:  curr  = c  elif c == "," or c == "]":  arr.append(int(curr))  curr = ""   lst, ind = arr[:-1], arr[-1]  return lst[ind]   foo(s) # 30  

Или, может быть,

 arr, ind = (  s.replace("][", ";").replace("[", "").replace("]", "").replace(" ", "").split(";") ) int(arr.split(",")[int(ind)])  

Комментарии:

1. Это тоже вариант, но, похоже, для этой довольно простой задачи потребуется много тяжелой работы.

Ответ №3:

Вы можете безопасно создавать AST с помощью входного сигнала, используя compile встроенный. Но вы не можете безопасно оценить AST. Поэтому вам придется самому пройти AST, собирая целые числа и составляя из них список. Если выражение так просто, как вы говорите, это не составит труда.

, string) mylist = literal_eval(m.group(1)) index = literal_eval(m.group(2)) value = mylist[index] # gives value 2

Комментарии:

1. А, понял. Это похоже на попытку разработать свой собственный способ компиляции этого кода. Надеюсь, в будущих версиях Python будут лучшие варианты, я надеюсь.

Ответ №2:

Если это так же просто, как выбрать целое число из списка, вы можете проанализировать его самостоятельно.


Или, может быть,


Комментарии:

1. Это тоже вариант, но, похоже, для этой довольно простой задачи потребуется много тяжелой работы.

Ответ №3:

Вы можете безопасно создавать AST с помощью входного сигнала, используя compile встроенный. Но вы не можете безопасно оценить AST. Поэтому вам придется самому пройти AST, собирая целые числа и составляя из них список. Если выражение так просто, как вы говорите, это не составит труда.