Оценка в python? - PullRequest
       85

Оценка в python?

0 голосов
/ 25 апреля 2020
available_items = {"health potion": 10, "cake of the cure": 5, "green elixir": 20, "strength sandwich": 25, "stamina grains": 15, "power stew": 30}

health_points = 20

health_points += available_items.pop("stamina grains")

Когда я запускаю этот код, значение ключа "зерна выносливости" добавляется, и зерна выносливости удаляются из словаря available_items.

Но Python вычисляет выражения слева направо, так что Я должен сначала удалить ключ "выносливости", поэтому к health_points.

не следует добавлять ничего. Я не совсем понимаю, как Python оценивает выражения. Может кто-нибудь уточнить это, а также дать мне некоторые ресурсы о том, как Python оценивает выражения?

Ответы [ 3 ]

3 голосов
/ 25 апреля 2020

Если вы посмотрите здесь: Приоритет оператора , вы увидите, что «вызов» находится в нижней части таблицы, поэтому он выполняется первым. После выполнения этого первого шага вы можете переписать оператор следующим образом: health_points += 15.

Немного выше сложение, которое выполняется следующим (+= - это сокращение от сложения: health_points = health_points + available_items.pop("stamina grains")). И наверху это назначение, так что это выполняется последним. В результате health_points == 35.

1 голос
/ 25 апреля 2020

Из первого результата Google поиска "Python + словарь + поп" (акцент мой):

Метод pop() удаляет и возвращает элемент из словаря с заданным ключом.

Таким образом, верно, что действие pop выполнено первым, и также верно, что оно удаляет элемент из словаря. , но также возвращает это значение, которое используется для обновления healt_points переменной.

В деталях , в соответствии с таблицей порядка оценки :

Python вычисляет выражения слева направо. Обратите внимание, что при оценке присваивания правая часть вычисляется перед левой частью.

Итак, учитывая выражение

health_points = health_points  + available_items.pop("stamina grains")
  1. Мы имеем задание, поэтому правая часть будет оцениваться первой: health_points + available_items.pop("stamina grains")
  2. С правой стороны оценка выполняется слева направо: health_points вычисляется первой и ее значение равно 20
  3. Теперь available_items.pop("stamina grains") оценивается. Вызовите pop метод для available_items словаря
  4. Ключ "stamina grains" найден, и его значение (15) возвращено
  5. В качестве побочного эффекта , pop удаляет "stamina grains" из словаря. В любом случае возвращается значение 15: это просто целое число, представляющее результат метода. Он больше не связан с существованием элемента словаря
  6. Выражение теперь health_points = 20 + 15. Правая оценка - это целое число 35, которое теперь можно присвоить health_points. Это завершает оценку левой стороны
1 голос
/ 25 апреля 2020

CPython реализован как стековая машина . Если вы хотите точно увидеть, в каком порядке вычисляются подвыражения, может быть полезно разобрать их:

>>> from dis import dis
>>> dis('''
... available_items = {"health potion": 10, "cake of the cure": 5, "green elixir": 20, "strength sandwich": 25, "stamina grains": 15, "power stew": 30}
...
... health_points = 20
...
... health_points += available_items.pop("stamina grains")
... ''')
  2           0 LOAD_CONST               0 (10)
              2 LOAD_CONST               1 (5)
              4 LOAD_CONST               2 (20)
              6 LOAD_CONST               3 (25)
              8 LOAD_CONST               4 (15)
             10 LOAD_CONST               5 (30)
             12 LOAD_CONST               6 (('health potion', 'cake of the cure', 'green elixir', 'strength sandwich', 'stamina grains', 'power stew'))
             14 BUILD_CONST_KEY_MAP      6
             16 STORE_NAME               0 (available_items)

  4          18 LOAD_CONST               2 (20)
             20 STORE_NAME               1 (health_points)

  6          22 LOAD_NAME                1 (health_points)
             24 LOAD_NAME                0 (available_items)
             26 LOAD_METHOD              2 (pop)
             28 LOAD_CONST               7 ('stamina grains')
             30 CALL_METHOD              1
             32 INPLACE_ADD
             34 STORE_NAME               1 (health_points)
             36 LOAD_CONST               8 (None)
             38 RETURN_VALUE

В то время как подвыражения (в основном) оценивают слева направо, приоритет операторов и скобки могут изменить это. И назначение - это утверждение, а не выражение. Даже если += находится слева от .pop(), вы можете видеть, что вызов происходит до назначения в скомпилированном байт-коде.

Обратите внимание, что вызов (pop) помещает свое возвращаемое значение в стек по команде CALL_METHOD, поэтому он может использоваться INPLACE_ADD. В это время значение не указывается в dict, только в стеке, но ни в коем случае значение не было потеряно. И результат добавления доступен для инструкции STORE_NAME после этого.

...