Поведение операторов увеличения и уменьшения в Python
Как мне использовать операторы предварительного увеличения / уменьшения (++
, --
), как в C ++?
Почему ++count
выполняется, но не изменяет значение переменной?
Переведено автоматически
Ответ 1
++
это не оператор. Это два +
оператора. +
Оператор - это оператор identity, который ничего не делает. (Уточнение: унарные операторы +
и -
работают только с числами, но я предполагаю, что вы не ожидаете, что гипотетический ++
оператор будет работать со строками.)
++count
Разбирается следующим образом
+(+count)
Что переводится как
count
Вы должны использовать немного более длинный оператор +=
, чтобы делать то, что вы хотите сделать:
count += 1
Я подозреваю, что операторы ++
и --
были опущены для согласованности и простоты. Я не знаю точного аргумента, который Гвидо ван Россум привел для принятия решения, но я могу представить несколько аргументов:
- Упрощенный синтаксический анализ. Технически синтаксический анализ
++count
неоднозначен, поскольку это могло бы быть+
,+
,count
(два унарных+
оператора) так же легко, как это могло бы быть++
,count
++
(один унарный,, оператор). Это не является существенной синтаксической двусмысленностью, но она существует. - Более простой язык.
++
это не более чем синоним+= 1
. Это было сокращение, изобретенное потому, что компиляторы C были глупы и не знали, как оптимизироватьa += 1
вinc
инструкции, которые есть у большинства компьютеров. В наше время оптимизирующих компиляторов и языков, интерпретирующих байт-код, добавление операторов в язык, позволяющих программистам оптимизировать свой код, обычно вызывает неодобрение, особенно в таком языке, как Python, который разработан так, чтобы быть последовательным и читаемым. - Запутанные побочные эффекты. Одна из распространенных ошибок новичков в языках с
++
операторами заключается в смешивании различий (как в приоритете, так и в возвращаемом значении) между операторами до и после инкремента / декремента, и Python любит устранять языковые "ошибки". Проблемы с приоритетом до / после инкремента в C довольно сложны, и их невероятно легко испортить.
Ответ 2
В Python нет операторов до и после инкремента.
В Python целые числа неизменяемы. То есть вы не можете их изменить. Это потому, что целочисленные объекты могут использоваться под несколькими именами. Попробуйте это:
>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True
a и b, приведенные выше, на самом деле являются одним и тем же объектом. Если вы увеличили a, вы также увеличили бы b . Это не то, что вы хотите. Поэтому вам нужно переназначить. Вот так:
b = b + 1
Многие программисты на C, которые использовали python, хотели иметь оператор увеличения, но этот оператор выглядел бы так, как будто он увеличивает объект, в то время как на самом деле он переназначает его. Поэтому добавленные операторы -=
и +=
должны быть короче, чем b = b + 1
, при этом быть более понятными и гибкими, чем b++
, поэтому большинство людей будут увеличивать с:
b += 1
Который будет переназначен b
на b+1
. Это не оператор инкремента, потому что он не увеличивает b
, он переназначает его.
Вкратце: Python ведет себя здесь по-другому, потому что это не C, и это не низкоуровневая оболочка машинного кода, а высокоуровневый динамический язык, где приращения не имеют смысла, а также не так необходимы, как в C, где вы используете их, например, каждый раз, когда у вас есть цикл.
Ответ 3
В то время как другие ответы верны, поскольку они показывают, что обычно делает простое число +
(а именно, оставляют число таким, какое оно есть, если оно равно единице), они неполны, поскольку не объясняют, что происходит.
Если быть точным, +x
вычисляется как x.__pos__()
и ++x
to x.__pos__().__pos__()
.
Я мог бы представить себе ОЧЕНЬ странную структуру классов (Дети, не делайте этого дома!) вот так:
class ValueKeeper(object):
def __init__(self, value): self.value = value
def __str__(self): return str(self.value)
class A(ValueKeeper):
def __pos__(self):
print('called A.__pos__')
return B(self.value - 3)
class B(ValueKeeper):
def __pos__(self):
print('called B.__pos__')
return A(self.value + 19)
x = A(430)
print(x, type(x))
print(+x, type(+x))
print(++x, type(++x))
print(+++x, type(+++x))
Ответ 4
TL; DR
В Python нет унарных операторов инкремента / декремента (--
/++
). Вместо этого для увеличения значения используйте
a += 1
Подробнее и подводные камни
Но здесь будьте осторожны. Если вы переходите с C, то в python даже это отличается. В Python нет "переменных" в том смысле, в каком это имеет C, вместо этого python использует имена и объекты, а в python int
они неизменяемы.
итак, допустим, вы делаете
a = 1
Что это означает в python: создайте объект типа, int
имеющий значение 1
, и привяжите к нему имя a
. Объект является экземпляром, int
имеющим значение1
, и на него ссылается имя a
. Имя a
и объект, на который оно ссылается, различны.
Теперь допустим, что вы делаете
a += 1
Поскольку int
s неизменяемы, здесь происходит следующее:
- найдите объект, на который
a
ссылается (это объект сint
идентификатором0x559239eeb380
) - найдите значение object
0x559239eeb380
(оно есть1
) - добавьте 1 к этому значению (1 + 1 = 2)
- создайте новый
int
объект со значением2
(у него есть идентификатор объекта0x559239eeb3a0
) - повторно привяжите имя
a
к этому новому объекту - Теперь
a
ссылается на object0x559239eeb3a0
, а на исходный объект (0x559239eeb380
) больше не ссылается имяa
. Если нет никаких других имен, ссылающихся на исходный объект, позже он будет собран как мусор.
Попробуйте сами:
a = 1
print(hex(id(a)))
a += 1
print(hex(id(a)))