Python에서 증가 및 감소 연산자의 동작
사전 증가 / 감소 연산자가 변수 (예 :)에 적용될 수 있습니다 ++count
. 컴파일되지만 실제로 변수의 값을 변경하지는 않습니다!
파이썬에서 사전 증가 / 감소 연산자 (++ /-)의 동작은 무엇입니까?
Python이 C / C ++에서 볼 수있는 이러한 연산자의 동작과 다른 이유는 무엇입니까?
++
운영자가 아닙니다. 두 명의 +
연산자입니다. +
운영자는이다 신원 아무것도하지 않는다 연산자. (설명 : 단항 연산자 +
와 -
단항 연산자는 숫자에서만 작동하지만 가상 ++
연산자가 문자열에서 작동 할 것이라고 예상하지 않을 것이라고 가정 합니다.
++count
다음으로 구문 분석
+(+count)
어떤 의미로
count
+=
원하는 작업을 수행 하려면 약간 더 긴 연산자 를 사용해야합니다 .
count += 1
일관성과 단순성을 위해 ++
및 --
연산자가 제외 되었다고 생각합니다 . 나는 귀도 반 로섬이 결정에 대해 준 정확한 주장을 모르지만 몇 가지 주장을 상상할 수 있습니다.
- 더 간단한 구문 분석. 기술적으로 파싱
++count
은 모호합니다+
.+
,,count
(두 개의 단항+
연산자)처럼 쉽게++
,count
(하나의 단항++
연산자). 중요한 구문 모호성은 아니지만 존재합니다. - 더 간단한 언어.
++
의 동의어 일뿐입니다+= 1
. 그것은 C 컴파일러가 어리 석고 대부분의 컴퓨터가 가지고a += 1
있는inc
명령어 로 최적화하는 방법을 몰랐기 때문에 발명 된 속기 입니다. 컴파일러와 바이트 코드 해석 언어를 최적화하는 오늘날, 프로그래머가 코드를 최적화 할 수 있도록 언어에 연산자를 추가하는 것은 일반적으로 특히 일관되고 읽을 수 있도록 설계된 Python과 같은 언어에서 눈살을 찌푸립니다. - 혼란스러운 부작용.
++
연산자 를 사용하는 언어에서 흔히 발생하는 한 가지 오류 는 사전 및 사후 증가 / 감소 연산자 간의 차이 (우선 순위 및 반환 값 모두)를 혼합하는 것입니다. Python은 언어 "gotcha"-s를 제거하는 것을 좋아합니다. 우선 순위 문제 의 C에서 사전 / 사후 증가는 엉망에 놀라 울 정도로 쉽게 꽤 털이합니다.
증가 또는 감소를 원할 때 일반적으로 정수에 대해 수행합니다. 이렇게 :
b++
그러나 파이썬에서 정수는 불변 입니다. 그것은 당신이 그들을 바꿀 수 없다는 것입니다. 정수 객체를 여러 이름으로 사용할 수 있기 때문입니다. 이 시도:
>>> b = 5
>>> a = 5
>>> id(a)
162334512
>>> id(b)
162334512
>>> a is b
True
위의 a와 b는 실제로 동일한 객체입니다. a를 증가 시키면 b도 증가합니다. 그것은 당신이 원하는 것이 아닙니다. 따라서 재 할당해야합니다. 이렇게 :
b = b + 1
또는 더 간단합니다.
b += 1
에 재 할당 b
됩니다 b+1
. 증분 연산자가 아닙니다. 증분하지 않기 b
때문에 다시 할당합니다.
간단히 말해서, 파이썬은 여기서 다르게 동작합니다. 왜냐하면 그것은 C가 아니고 기계 코드를 둘러싼 저수준 래퍼가 아니라 증가가 의미가없고 C 에서처럼 필요하지 않은 고수준 동적 언어이기 때문입니다. , 예를 들어 루프가있을 때마다 사용합니다.
다른 답변은 단순한 사람이 +
일반적으로 하는 일 (즉, 숫자를 그대로 두는 것)을 보여주는 한 정확하지만 어떤 일이 발생하는지 설명하지 않는 한 불완전합니다.
정확히 말하면 및 로 +x
평가 됩니다 .x.__pos__()
++x
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)
파이썬에는 이러한 연산자가 없지만 실제로 필요한 경우 동일한 기능을 가진 함수를 작성할 수 있습니다.
def PreIncrement(name, local={}):
#Equivalent to ++name
if name in local:
local[name]+=1
return local[name]
globals()[name]+=1
return globals()[name]
def PostIncrement(name, local={}):
#Equivalent to name++
if name in local:
local[name]+=1
return local[name]-1
globals()[name]+=1
return globals()[name]-1
용법:
x = 1
y = PreIncrement('x') #y and x are both 2
a = 1
b = PostIncrement('a') #b is 1 and a is 2
함수 내에서 지역 변수를 변경하려면 locals ()를 두 번째 인수로 추가해야합니다. 그렇지 않으면 전역 변경을 시도합니다.
x = 1
def test():
x = 10
y = PreIncrement('x') #y will be 2, local x will be still 10 and global x will be changed to 2
z = PreIncrement('x', locals()) #z will be 11, local x will be 11 and global x will be unaltered
test()
또한 이러한 기능으로 다음을 수행 할 수 있습니다.
x = 1
print(PreIncrement('x')) #print(x+=1) is illegal!
그러나 제 생각에는 접근 방식을 따르는 것이 훨씬 더 명확합니다.
x = 1
x+=1
print(x)
감소 연산자 :
def PreDecrement(name, local={}):
#Equivalent to --name
if name in local:
local[name]-=1
return local[name]
globals()[name]-=1
return globals()[name]
def PostDecrement(name, local={}):
#Equivalent to name--
if name in local:
local[name]-=1
return local[name]+1
globals()[name]-=1
return globals()[name]+1
나는 자바 스크립트를 파이썬으로 번역하는 모듈에서 이러한 함수를 사용했습니다.
Python에서는 Common Lisp, Scheme 또는 Ruby와 같은 언어와 달리 표현식과 문 사이의 구분이 엄격하게 적용됩니다.
So by introducing such operators, you would break the expression/statement split.
For the same reason you can't write
if x = 0:
y = 1
as you can in some other languages where such distinction is not preserved.
Yeah, I missed ++ and -- functionality as well. A few million lines of c code engrained that kind of thinking in my old head, and rather than fight it... Here's a class I cobbled up that implements:
pre- and post-increment, pre- and post-decrement, addition,
subtraction, multiplication, division, results assignable
as integer, printable, settable.
Here 'tis:
class counter(object):
def __init__(self,v=0):
self.set(v)
def preinc(self):
self.v += 1
return self.v
def predec(self):
self.v -= 1
return self.v
def postinc(self):
self.v += 1
return self.v - 1
def postdec(self):
self.v -= 1
return self.v + 1
def __add__(self,addend):
return self.v + addend
def __sub__(self,subtrahend):
return self.v - subtrahend
def __mul__(self,multiplier):
return self.v * multiplier
def __div__(self,divisor):
return self.v / divisor
def __getitem__(self):
return self.v
def __str__(self):
return str(self.v)
def set(self,v):
if type(v) != int:
v = 0
self.v = v
You might use it like this:
c = counter() # defaults to zero
for listItem in myList: # imaginary task
doSomething(c.postinc(),listItem) # passes c, but becomes c+1
...already having c, you could do this...
c.set(11)
while c.predec() > 0:
print c
....or just...
d = counter(11)
while d.predec() > 0:
print d
...and for (re-)assignment into integer...
c = counter(100)
d = c + 223 # assignment as integer
c = c + 223 # re-assignment as integer
print type(c),c # <type 'int'> 323
...while this will maintain c as type counter:
c = counter(100)
c.set(c + 223)
print type(c),c # <class '__main__.counter'> 323
EDIT:
And then there's this bit of unexpected (and thoroughly unwanted) behavior,
c = counter(42)
s = '%s: %d' % ('Expecting 42',c) # but getting non-numeric exception
print s
...because inside that tuple, getitem() isn't what used, instead a reference to the object is passed to the formatting function. Sigh. So:
c = counter(42)
s = '%s: %d' % ('Expecting 42',c.v) # and getting 42.
print s
...or, more verbosely, and explicitly what we actually wanted to happen, although counter-indicated in actual form by the verbosity (use c.v
instead)...
c = counter(42)
s = '%s: %d' % ('Expecting 42',c.__getitem__()) # and getting 42.
print s
TL;DR
Python does not have unary increment/decrement operators (--
/++
). Instead, to increment a value, use
a += 1
More detail and gotchas
But be careful here. If you're coming from C, even this is different in python. Python doesn't have "variables" in the sense that C does, instead python uses names and objects, and in python int
s are immutable.
so lets say you do
a = 1
What this means in python is: create an object of type int
having value 1
and bind the name a
to it. The object is an instance of int
having value 1
, and the name a
refers to it. The name a
and the object to which it refers are distinct.
Now lets say you do
a += 1
Since int
s are immutable, what happens here is as follows:
- look up the object that
a
refers to (it is anint
with id0x559239eeb380
) - look up the value of object
0x559239eeb380
(it is1
) - add 1 to that value (1 + 1 = 2)
- create a new
int
object with value2
(it has object id0x559239eeb3a0
) - rebind the name
a
to this new object - Now
a
refers to object0x559239eeb3a0
and the original object (0x559239eeb380
) is no longer refered to by the namea
. If there aren't any other names refering to the original object it will be garbage collected later.
Give it a try yourself:
a = 1
print(hex(id(a)))
a += 1
print(hex(id(a)))
참고URL : https://stackoverflow.com/questions/1485841/behaviour-of-increment-and-decrement-operators-in-python
'Program Tip' 카테고리의 다른 글
JavaScript의 HTTP GET 요청? (0) | 2020.09.29 |
---|---|
과 (0) | 2020.09.29 |
CodeMash 2012의 'Wat'강연에서 언급 된 이러한 기괴한 JavaScript 동작에 대한 설명은 무엇입니까? (0) | 2020.09.29 |
Python의 mkdir -p 기능 (0) | 2020.09.29 |
Facebook 및 새 Twitter URL의 shebang / hashbang (#!)은 무엇입니까? (0) | 2020.09.29 |