Безопасно ли самоназначение в Python? - PullRequest
0 голосов
/ 03 декабря 2018

Этот вопрос меня смутил в наши дни: что происходит, когда переменная присваивается самой себе в Python?Например,

a = a if (a>b) else b

Я очень мало знаю о механизме подсчета ссылок и не знаю об этом вопросе.Помогите мне, если вы знаете ответ, спасибо!

1 Ответ

0 голосов
/ 03 декабря 2018

Совершенно безопасно.Python будет упорядочивать все после знака =, поэтому выражение вычисляется до назначения переменной. Я не думаю, что есть какой-либо язык программирования, где это было бы небезопасно (см. Комментарий @ hadik ниже).


что происходит с подсчетом ссылокэтой переменной при самостоятельном назначении?

Короче говоря, это будет правильно.

В более длинном ответе, чтобы ответить на этот вопрос, лучше взглянуть на разборку, выполнив этот код:

import dis                   
def f(a, b): 
    a = a if (a>b) else b                                               
dis.dis(f)

Аннотированная разборка:

      # the objects pointed by `a` and `b` starts with a positive refcount as they're part of the function argument

      # increment refcount for the object pointed by `a` and `b`
      0 LOAD_FAST                0 (a)
      2 LOAD_FAST                1 (b)

      # COMPARE_OP (usually) returns boolean True/False
      # increment the refcount of the boolean value
      # and decrement the refcount of the object pointed by `a` and `b`
      4 COMPARE_OP               4 (>)

      # decrements the refcount of that boolean value
      6 POP_JUMP_IF_FALSE       12

      # increment refcount for the object pointed by `a`
      8 LOAD_FAST                0 (a)

     10 JUMP_FORWARD             2 (to 14)

      # increment refcount for the object pointed by `b`
>>   12 LOAD_FAST                1 (b)

      # decrement refcount for the object originally pointed by `a`
>>   14 STORE_FAST               0 (a)

     16 LOAD_CONST               0 (None)
     18 RETURN_VALUE

НекоторыеСправочная информация: Python VM является стековым компьютером.Операция LOAD_ * помещает значение в стек (и увеличивает его refcount, поскольку в стеке теперь есть ссылка на объект), и большинство других операций извлекают значения из стека и переносят вычисленный результат в стек (уменьшая refcountпотребляемые значения и приращение результата).Операция STORE_ * перемещает объект из верхней части стека в переменную (и уменьшает счетчик исходного объекта, на который ссылается переменная; для этого не нужно изменять счет подсчета перемещаемого объекта, поскольку он выталкивает стек и устанавливаетпеременная фактически не меняет refcount).

Короче говоря, Python refcount всегда делает правильные вещи, даже когда он многопоточный (это благодаря GIL).Вы действительно никогда не должны беспокоиться о пересчете, если объект доступен из области видимости, он не будет собирать мусор.

...