파이썬에 ++ 및 ---- 연산자가없는 이유는 무엇입니까?


답변:


443

이해가되지 않기 때문이 아닙니다. "x ++"를 "x + = 1로 정의하여 x의 이전 바인딩으로 평가"하는 것이 좋습니다.

원래의 이유를 알고 싶다면 오래된 파이썬 메일 링리스트를 살펴 보거나 거기에 있던 누군가에게 물어봐야합니다 (예 : 귀도). 그러나 사실 이후 정당화하기는 쉽습니다.

다른 언어만큼 간단한 증감이 필요하지 않습니다. for(int i = 0; i < 10; ++i)파이썬 과 같은 것을 자주 쓰지 않습니다 . 대신 당신은 같은 일을 for i in range(0, 10)합니다.

거의 자주 필요하지 않기 때문에 고유 한 구문을 제공 할 이유가 훨씬 적습니다. 증분해야 할 때 +=일반적으로 괜찮습니다.

그것이 의미가 있는지, 할 수 있는지, 할 수 있는지, 할 수 있는지에 대한 결정은 아닙니다. 이점이 언어의 핵심 구문에 추가 할 가치가 있는지에 대한 질문입니다. 이것은 postinc, postdec, preinc, predec의 네 가지 연산자이며 각각의 클래스 오버로드가 필요합니다. 그것들은 모두 명시되고 테스트되어야한다. 언어에 opcode를 추가합니다 (더 큰 VM 엔진을 의미 함). 논리적 증가를 지원하는 모든 클래스는 (위에이를 구현해야 +=하고 -=).

이 모두와 +=와 중복 -=되므로 순손실이됩니다.


98
array = [i ++]와 같이 + = /-=로 깔끔하게 처리되지 않은 것을 사용하는 것이 종종 유용합니다.
터너 헤이즈

102
@ thayes : 그것은 파이썬에서 일반적인 패턴이 아닙니다.
Glenn Maynard

9
@thayes 루프 안에있을 것이기 때문에 i직접 루프를 반복 할 수도 있습니다. 실제로 필요할 때 사용할 수없는 경우array.append()
Tobias Kienzler

31
더 큰 관심사는 가독성과 예측 가능성입니다. 나의 C 시절에, 나는 i++++i... 사이의 구별에 대한 오해에서 비롯된 충분한 버그 이상을 보았습니다 .
Charles Duffy

5
사후 정당화에 추가 : 내가 만난에 프로젝트 나 작업에 문제에서 C ++ 코드 고통의 공정한 금액 (많은 사람이 자신의 인생에서와해야 이상) ++--같은 방법으로 사용되는 정의되지 않았거나 지정되지 않은 결과가 행동. 복잡하고 수정하기 어려운 구문 분석 코드를 작성할 수 있습니다.
Brian Vandenberg

84

내가 쓴이 원래의 대답은 컴퓨팅 민속학의 신화입니다. Dennis Ritchie 가 ACM 커뮤니케이션 편집자에게 보낸 편지에서 2012 년 7 월 doi : 10.1145 / 2209249.2209251에 언급 된 것처럼 "역사적으로 불가능하다"고 주장했습니다.


C 증분 / 감소 연산자는 C 컴파일러가 똑똑하지 않은 시점에 발명되었으며 저자는 기계 언어 연산자를 사용해야하는 직접적인 의도를 지정할 수 있기를 원했습니다. 할 수 있습니다

load memory
load 1
add
store memory

대신에

inc memory 

PDP-11 은 각각 *++p및에 해당하는 "자동 증가"및 "자동 증가 지연"명령도 지원 *p++했습니다. 몹시 호기심이 많으면 설명서 의 섹션 5.3을 참조하십시오 .

컴파일러는 C 구문에 내장 된 고급 최적화 트릭을 처리 할 수있을만큼 똑똑하기 때문에 지금은 구문상의 편의에 불과합니다.

파이썬에는 의도를 사용하지 않기 때문에 의도를 어셈블러에 전달하는 트릭이 없습니다.


4
자바 스크립트에는 ++가 있습니다. 나는 이것이 "어셈블러에게 의도를 전달하는 속임수"라고 생각하지 않는다. 또한 파이썬에는 바이트 코드가 있습니다. 그래서 나는 그 이유가 다른 것이라고 생각합니다.
Nathan Davis

13
이 "컴파일러에 힌트 제공"사업은 실제로 신화입니다. 솔직히 말해서, 그것은 어떤 언어에 멍청한 추가이며 다음 두 가지 교훈을 위반합니다. 1. 컴퓨터가 읽을 수 있도록 코딩하지 않고 다른 엔지니어가 읽을 수 있도록 코딩합니다. 그리고 2. 유능한 엔지니어가 읽을 수있는 코드를 작성하지 않고, 오전 3시에 소진하여 카페인을 타면서 유능한 엔지니어가 읽을 수있는 코드를 작성합니다.

3
@ tgm1024 공평하게, 초당 10-30 문자의 반이중 텔레 타입으로 코딩 할 때 다음 주 전에 입력 할 수 있도록 코딩합니다.
msw

4
@ tgm1024 Unix와 C는 PDP-11에서 초기 개발의 대부분을 보았으며 이는 사용자 통신에 매우 느린 텔레타이프를 사용했습니다. 당신이 그 죽은 잘하지만 오늘 다시 그 기계에 대한 코딩은 대부분 바보입니다, 그것은 병목 현상 인간 / 기계 인터페이스했다. 당신이 결코 필요하지 않으면 천천히 작동하는 것을 상상하기 어렵습니다.
msw

65

나는 항상 파이썬의이 선과 관련이 있다고 가정했습니다.

이를 수행 할 수있는 분명한 방법은 하나만 있어야합니다.

x ++와 x + = 1은 똑같은 작업을 수행하므로 둘 다 가질 이유가 없습니다.


10
one--0입니까?
Andre Holzner

25
one--문장에서 하나이지만 바로 뒤에 0입니다. 따라서이 '관념'은 증가 / 감소 연산자가 명백하지 않다는 것을 암시합니다.
Victor K

14
@EralpB + =를 삭제하면 x + = 10과 같은 작업을 수행 할 수 없습니다. + =는 ++의보다 일반적인 경우입니다.
Rory

8
또한 : "명시 성이 암시 적보다 낫다".
Ber

2
x + = 1은 표현식이 아니기 때문에 확실히 같지 않습니다. 이것은 문장이고 어떤 것으로도 평가되지 않습니다. 다음과 같은 작업을 수행 할 수 없습니다. 'row [col ++] = a; 행 [col ++] = b '. c ++에있는 pre-inc 및 post-inc 항목은 말할 것도 없습니다.
Uri

38

물론 우리는 "Guido가 그렇게 결정했다"고 말할 수는 있지만, 그 결정에 대한 이유는 문제라고 생각합니다. 몇 가지 이유가 있다고 생각합니다.

  • 문장과 표현을 혼합하여 사용하는 것은 좋지 않습니다. http://norvig.com/python-iaq.html 참조
  • 일반적으로 사람들이 읽기 어려운 코드를 작성하도록 권장합니다.
  • 이미 언급했듯이 파이썬에서는 필요하지 않은 언어 구현의 추가 복잡성

12
기쁜 사람은 마침내 진술과 표현 측면을 언급했습니다. C에서 대입은 표현식이므로 ++ 연산자입니다. 파이썬에서 할당은 문장이므로 ++가 있다면 할당 문장이어야 할 것입니다 (그리고 덜 유용하거나 필요합니다).
martineau

동의-그들이 진술이라면, 최소한 사후 운영자와 사전 운영자의 차이점에 대해 이야기하는 것은 절대적으로 의미가 없습니다.
Crowman

17

파이썬에서 정수는 불변이기 때문에 (int의 + =는 실제로 다른 객체를 반환합니다).

또한 ++ /-를 사용하면 사전 및 사후 증분 / 감소에 대해 걱정할 필요가 있으며 키를 한 번 더 입력하면 x+=1됩니다. 다시 말해, 이득이 거의 없어도 혼동을 피할 수 있습니다.


int는 C에서도 변경할 수 없습니다. 당신이 그렇게 생각하지 않는다면 C 컴파일러가 코드를 생성하도록하십시오 42++... 이것 (리터럴 상수 수정) 오래된 Fortran 컴파일러에서 실제로 가능했습니다 (또는 읽었습니다) : 모든 향후 사용 해당 프로그램 실행에서 해당 리터럴의 값은 실제로 다른 값을 갖습니다. 행복한 디버깅!
Lutz Prechelt

10
권리. 42는 리터럴 상수 입니다. 상수는 불변입니다 ( 적어도 있어야 합니다). 그렇다고 int일반적으로 C 가 불변 인 것은 아닙니다 . intC에서 단순히 메모리에있는 장소를 지정합니다. 그리고 그 장소의 비트는 매우 변경 가능합니다. 예를 들어의 참조를 만들고 해당 참조의 참조를 int변경할 수 있습니다. 이 변경 사항은 int해당 위치에 대한 모든 참조 (원래 변수 포함)에서 볼 수 있습니다 . 파이썬 정수 객체도 마찬가지입니다.
Nathan Davis

x + = 1은 결국 inc mem이되지 않습니다. 파이썬은 함수 호출을 실행하여 변수에 1을 더합니다. 한심하다.
팔라 돌핀

12

명쾌함!

파이썬은 명확성 에 대해 많은 것이 있으며, --a그 구조를 가진 언어를 배우지 않으면 프로그래머가 그 의미를 정확하게 추측하지 못할 것 입니다.

파이썬은 또한에 대해 많은입니다 실수를 초대 구조 피++운영자가 결함의 풍부한 소스 것으로 알려져됩니다. 이 두 가지 이유는 파이썬에서 그 연산자를 갖기에 충분하지 않습니다.

파이썬이 들여 쓰기를 사용하여 시작 / 종료 브라케팅 또는 필수 끝 표시와 같은 구문 적 수단보다는 블록을 표시한다는 결정은 대체로 동일한 고려 사항을 기반으로합니다.

예를 들어, 2005 년 에 조건부 연산자 (C cond ? resultif : resultelse:)를 파이썬에 도입하는 것에 관한 토론을 살펴 보십시오. 적어도 첫 번째 메시지를 읽으십시오.토론결정 메시지 (이전에 동일한 주제에 대해 여러 개의 선구자가 있음 .

퀴즈 : 자주 언급되는 PEP는 "Python Extension Proposal" PEP 308 입니다. LC는 list comprehension을 의미 하고 GE는 generator expression을 의미 합니다 (그리고 혼동하더라도 걱정할 필요가 없습니다. 파이썬의 복잡한 부분은 아닙니다).


10

파이썬에 ++연산자가 없는 이유에 대한 나의 이해 는 다음과 같습니다. 파이썬으로 이것을 작성할 때 a=b=c=1동일한 객체 (값 1)를 가리키는 세 개의 변수 (라벨)가 나타납니다. 객체 메모리 주소를 반환하는 id 함수를 사용하여이를 확인할 수 있습니다.

In [19]: id(a)
Out[19]: 34019256

In [20]: id(b)
Out[20]: 34019256

In [21]: id(c)
Out[21]: 34019256

세 가지 변수 (라벨)는 모두 같은 객체를 가리 킵니다. 이제 변수 중 하나를 증가시키고 그것이 메모리 주소에 어떻게 영향을 미치는지보십시오 :

In [22] a = a + 1

In [23]: id(a)
Out[23]: 34019232

In [24]: id(b)
Out[24]: 34019256

In [25]: id(c)
Out[25]: 34019256

a변수가 변수 b및 로 다른 객체를 가리키는 것을 볼 수 있습니다 c. 당신이 a = a + 1그것을 사용했기 때문에 분명합니다. 다시 말해 label에 완전히 다른 객체를 할당합니다 a. a++변수에 할당하지 않았다고 제안 할 수 있다고 상상해보십시오.a 새 객체에 오래된 객체를 래터 증가 시킨다는 . 이 모든 것은 혼란을 최소화하기위한 IMHO입니다. 더 잘 이해하려면 파이썬 변수의 작동 방식을 참조하십시오.

파이썬에서 함수가 호출자가 인식 한 일부 인수를 수정할 수 있지만 다른 인수는 수정할 수없는 이유는 무엇입니까?

파이썬은 값에 의한 호출입니까, 아니면 참조에 의한 호출입니까? 둘 다.

파이썬은 가치 또는 참조로 전달합니까?

파이썬은 참조에 의한 전달입니까, 값에 의한 전달입니까?

파이썬 : 참조로 변수를 전달하는 방법은 무엇입니까?

파이썬 변수와 메모리 관리 이해

파이썬에서 가치에 따른 행동 모방

파이썬 함수는 참조로 호출

Pythonista와 같은 코드 : 관용적 파이썬


9

그것은 단지 그런 식으로 설계되었습니다. 증가 및 감소 연산자는 바로 가기입니다 x = x + 1. 파이썬은 일반적으로 작업을 수행하는 대체 수단의 수를 줄이는 설계 전략을 채택했습니다. 확장 할당 은 파이썬에서 연산자를 증가 / 감소시키는 가장 가까운 것이며, 파이썬 2.0까지 추가되지 않았습니다.


3
예, 친구, 당신은로 바꿀 수 return a[i++]있습니다 return a[i=i+1].
Luís de Sousa

7

나는 파이썬을 처음 접했지만 그 이유는 언어 내에서 가변 객체와 불변 객체 사이의 강조 때문이라고 생각합니다. 이제 x ++을 x = x + 1로 쉽게 해석 할 수 있다는 것을 알고 있지만 변경할 수없는 객체를 제자리에서 늘리는 것처럼 보입니다 .

내 추측 / 느낌 / 직감.


이 양태에서, x++근접하는 것이다 x += 1보다 x = x + 1이들 두 개체 변경할뿐만 차이를 만드는.
glglgl 10

4

첫째, 파이썬은 C에 의해서만 간접적으로 영향을받습니다. ABC에 크게 영향을받으며 , 이러한 연산자 는없는 것 같습니다. 따라서 파이썬에서도 찾을 수 없다는 것은 놀라운 일이 아닙니다.

둘째, 다른 사람들이 말했듯이 증가 및 감소는 +=-= 이미.

셋째, ++-- 연산자 집합에 에는 일반적으로 접두사 및 접미사 버전을 모두 지원하는 것이 포함됩니다. C와 C ++에서 이것은 모든 종류의 "사랑스러운"구성체가 파이썬이 받아들이는 단순성과 직설 성의 정신에 위배되는 것처럼 보일 수 있습니다.

예를 들어, C 문 while(*t++ = *s++);은 숙련 된 프로그래머, 그것을 배우는 사람에게는 단순하고 우아하게 보일 수 있지만 간단합니다. 접두사와 접두사 증가 및 감소를 혼합하여 던져보십시오. 심지어 많은 전문가들도 그만두고 조금 생각해야합니다.


3

나는 그것이 "명시적인 것이 묵시적인 것보다 낫다"는 파이썬 신조에서 나온 것이라고 믿는다.


글쎄, 파이썬에서 "시작"과 "종료"문장을 명시 적으로 쓰지 않습니까? 성명서에 동의하더라도 그 경계에는 한계가 있다고 생각합니다. 우리가 그 경계에 대해 논쟁 할 수는 있지만, 나는 우리 모두가 동의 할 수 있다고 생각합니다. 그리고 그 결정에 대한 많은 의견과 칭의가 있기 때문에, 나는 그것이 분명한 선택이라고 생각하지 않습니다. 적어도 명시 적으로 언급 된 출처를 찾을 수 없습니다
Hasan Ammori

3

@GlennMaynard 가 다른 언어와 비교하여 문제를보고 있기 때문일 수 있지만 파이썬에서는 파이썬 방식으로 일을합니다. '왜'질문이 아닙니다. 거기에 있으며와 같은 효과를 낼 수 있습니다 x+=. 에서 파이썬의 선 , 주어진 : "만 문제를 해결하는 하나 개의 방법이 있어야한다." 객관식은 예술 (표현의 자유)에서는 훌륭하지만 공학에서는 까다 롭습니다.


2

++사업자의 클래스는 부작용 표현입니다. 이것은 일반적으로 파이썬에서 찾을 수없는 것입니다.

같은 이유로 할당은 파이썬에서 표현식이 아니므로 일반적인 if (a = f(...)) { /* using a here */ }관용구를 막습니다.

마지막으로 연산자가 파이썬 참조 의미와 매우 일치하지 않는 것으로 생각됩니다. 파이썬에는 C / C ++에서 알려진 의미론을 가진 변수 (또는 포인터)가 없습니다.


1
테스트 / 표현식 / 목록 이해에서 부작용을 가진 함수를 호출하는 것을 막을 수 f(a)있는 a것은 없습니다.
Jean-François Fabre

1

이 연산자가 왜 C에 존재하는지 묻는 것이 더 좋은 질문 일 것입니다. 서론은 그것들을 '더 간결하고 종종 더 효율적'이라고 부릅니다. 이러한 조작이 항상 포인터 조작에서 발생한다는 사실이 도입에 일부 영향을 미쳤다고 생각합니다. 파이썬에서는 증분 최적화를 시도하는 것이 타당하지 않다고 결정되었을 것입니다 (사실 C에서 테스트를 수행했으며 gcc 생성 어셈블리는 두 경우를 모두 포함하지 않고 addl을 사용하는 것 같습니다) 포인터 산술; 그래서 그것은 한 가지 더 할 수있는 방법 일 것입니다. 우리는 파이썬이 그것을 싫어한다는 것을 알고 있습니다.


1

내가 이해 했으므로 메모리의 값이 변경되지 않았다고 생각합니다. x ++를 수행하면 c에서 메모리의 x 값이 변경됩니다. 그러나 파이썬에서는 모든 숫자를 변경할 수 없으므로 x가 x로 지정한 x의 주소는 x + 1이 아닙니다. x ++를 작성할 때 x가 실제로 발생하는 것은 x refrence가 x + 1이 저장된 메모리의 위치로 변경되거나 존재하지 않는 경우이 위치를 다시 만드는 것입니다.


1
그렇다면 이것 ++과 다른 점은 += 1무엇입니까?
Ber

1

해당 페이지에서 이미 좋은 답변을 완료하려면 다음 단계를 따르십시오.

++i단항 + 및-연산자를 손상시키는 접두사 ( )를 사용 하기로 결정했다고 가정 해 봅시다 .

오늘날에 의해 접두사 ++또는 --두 번이 단항 플러스 연산자를 수 있기 때문에, 아무것도하지 않는 두 번이나 단항 마이너스 (아무것도하지 않는다) (2 회 : 자체를 취소)

>>> i=12
>>> ++i
12
>>> --i
12

그래서 그것은 아마도 그 논리를 깨뜨릴 것입니다.


1

다른 답변은 반복기에 필요하지 않은 이유를 설명했지만 때로는 변수를 인라인으로 늘리도록 할당 할 때 유용합니다. 튜플과 여러 할당을 사용하여 동일한 효과를 얻을 수 있습니다.

b = ++a 된다 :

a,b = (a+1,)*2

그리고 b = a++된다 :

a,b = a+1, a

파이썬 3.8은 할당 소개하고 :=우리가 달성 할 수 있도록, 운영자 foo(++a)와 함께

foo(a:=a+1)

foo(a++) 그래도 여전히 애매합니다.


2
: = 양도는 불명예
nehem

0

나는 이것이 객체의 가변성과 불변성의 개념과 관련이 있다고 생각합니다. 2,3,4,5는 파이썬에서 불변입니다. 아래 이미지를 참조하십시오. 이 파이썬 프로세스까지 2는 고정 ID입니다.

상수 및 변수의 ID

x ++는 본질적으로 C와 같은 인플레 이스 증분을 의미합니다. C에서 x ++는 인플레 이스 증분을 수행합니다. 따라서 3은 여전히 ​​메모리에 존재하는 파이썬과 달리 x = 3이고 x ++는 메모리에서 3을 4로 증가시킵니다.

따라서 파이썬에서는 메모리에 값을 다시 만들 필요가 없습니다. 이것은 성능 최적화로 이어질 수 있습니다.

이것은 직감 기반의 답변입니다.


0

나는 이것이 오래된 스레드라는 것을 알고 있지만 ++ i의 가장 일반적인 사용 사례는 제공되지 않습니다. 제공된 인덱스가 없을 때 수동으로 세트를 인덱싱하는 것입니다. 이 상황에서 파이썬은 enumerate ()를 제공합니다

예 : 어떤 언어로든 foreach와 같은 구문을 사용하여 집합을 반복 할 때-예제를 위해 순서가 지정되지 않은 집합이라고 말하고 모든 것을 구별하기 위해 고유 한 색인이 필요합니다.

i = 0
stuff = {'a': 'b', 'c': 'd', 'e': 'f'}
uniquestuff = {}
for key, val in stuff.items() :
  uniquestuff[key] = '{0}{1}'.format(val, i)
  i += 1

이 경우 파이썬은 열거 방법을 제공합니다.

for i, (key, val) in enumerate(stuff.items()) :
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.