- 6. Expressions
- 6.1. Arithmetic conversions
- 6.2. Atoms
- 6.3. Primaries
- 6.4. Await expression
- 6.5. The power operator
- 6.6. Unary arithmetic and bitwise operations
- 6.7. Binary arithmetic operations
- 6.8. Shifting operations
- 6.9. Binary bitwise operations
- 6.10. Comparisons
- 6.11. Boolean operations
- 6.12. Assignment expressions
- 6.13. Conditional expressions
- 6.14. Lambdas
- 6.15. Expression lists
- 6.16. Evaluation order
- 6.17. Operator precedence
이 장에서는 파이썬에서 표현식 요소의 의미를 설명합니다.
구문 참고: 이 장과 다음 장에서는 어휘 분석이 아닌 구문을 설명하기 위해 확장된 BNF 표기법을 사용합니다. 구문 규칙의 형식이 다음과 같은 경우(대안 중 하나)
name ::= othername
의미론이 주어지지 않고, 이 형태의 이름의 의미론은 othername과 동일합니다.
6.1. Arithmetic conversions
아래 산술 연산자에 대한 설명에서 “숫자 인수가 공통 유형으로 변환됩니다”라는 문구를 사용하는 경우 이는 기본 제공 유형에 대한 연산자 구현이 다음과 같이 작동함을 의미합니다.
- 인수 중 하나가 복소수이면 다른 인수는 복소수로 변환됩니다.
- 그렇지 않고 인수 중 하나가 부동 소수점 숫자이면 다른 인수는 부동 소수점으로 변환됩니다.
- 그렇지 않으면 둘 다 정수여야 하며 변환이 필요하지 않습니다.
일부 추가 규칙이 특정 연산자에 적용됩니다(예: ‘%’ 연산자의 왼쪽 인수인 문자열). 확장은 자체 변환 동작을 정의해야 합니다.
6.2. Atoms
원자는 표현식의 가장 기본적인 요소입니다. 가장 간단한 원자는 식별자 또는 리터럴입니다. 괄호, 대괄호 또는 중괄호로 묶인 형식도 구문적으로 원자로 분류됩니다. 원자의 구문은 다음과 같습니다.
atom ::= identifier | literal | enclosure
enclosure ::= parenth_form | list_display | dict_display | set_display
| generator_expression | yield_atom
6.2.1. Identifiers (Names)
원자로 나타나는 식별자는 이름입니다. 어휘 정의에 대해서는 식별자 및 키워드 섹션을 참조하고 이름 지정 및 바인딩에 대한 문서는 이름 지정 및 바인딩 섹션을 참조하세요.
이름이 개체에 바인딩되면 원자의 평가가 해당 개체를 생성합니다. 이름이 바인딩되지 않은 경우 이름을 평가하려고 하면 NameError 예외가 발생합니다.
Private name mangling: 클래스 정의에서 텍스트로 나타나는 식별자가 두 개 이상의 밑줄 문자로 시작하고 두 개 이상의 밑줄로 끝나지 않는 경우 해당 클래스의 개인 이름으로 간주됩니다. 개인 이름은 코드가 생성되기 전에 더 긴 형식으로 변환됩니다. 변환은 선행 밑줄이 제거되고 단일 밑줄이 삽입된 클래스 이름을 이름 앞에 삽입합니다. 예를 들어 Ham이라는 클래스에서 발생하는 식별자 __spam은 _Ham__spam으로 변환됩니다. 이 변환은 식별자가 사용되는 구문 컨텍스트와 무관합니다. 변환된 이름이 너무 긴 경우(255자 초과) 구현 정의 잘림이 발생할 수 있습니다. 클래스 이름이 밑줄로만 구성된 경우 변환이 수행되지 않습니다.
6.2.2. Literals
Python은 문자열 및 바이트 리터럴과 다양한 숫자 리터럴을 지원합니다.
literal ::= stringliteral | bytesliteral
| integer | floatnumber | imagnumber
리터럴을 평가하면 주어진 값을 가진 주어진 유형(문자열, 바이트, 정수, 부동 소수점 숫자, 복소수)의 객체가 산출됩니다. 부동 소수점 및 허수(복소수) 리터럴의 경우 값을 근사화할 수 있습니다. 자세한 내용은 리터럴 섹션을 참조하십시오.
모든 리터럴은 변경할 수 없는 데이터 유형에 해당하므로 개체의 ID는 해당 값보다 덜 중요합니다. 동일한 값(프로그램 텍스트에서 동일한 항목 또는 다른 항목)을 가진 리터럴을 여러 번 평가하면 동일한 개체 또는 동일한 값을 가진 다른 개체를 얻을 수 있습니다.
6.2.3. Parenthesized forms
괄호로 묶인 형식은 괄호로 묶인 선택적 표현식 목록입니다.
parenth_form ::= "(" [starred_expression] ")"
괄호로 묶인 표현식 목록은 그 표현식 목록이 산출하는 모든 것을 산출합니다. 목록에 적어도 하나의 쉼표가 포함되어 있으면 튜플을 산출합니다. 그렇지 않으면 식 목록을 구성하는 단일 식을 생성합니다.
빈 괄호 쌍은 빈 튜플 객체를 생성합니다. 튜플은 변경할 수 없기 때문에 리터럴과 동일한 규칙이 적용됩니다(즉, 빈 튜플이 두 번 발생하면 동일한 객체가 생성될 수도 있고 생성되지 않을 수도 있음).
튜플은 괄호로 구성되지 않고 쉼표를 사용하여 구성됩니다. 예외는 괄호가 필요한 빈 튜플입니다. 식에서 괄호 안의 “아무것도”를 허용하지 않으면 모호성이 발생하고 일반적인 오타가 잡히지 않고 전달될 수 있습니다.
6.2.4. Displays for lists, sets and dictionaries
목록을 구성하기 위해 집합 또는 사전 Python은 “디스플레이”라는 특수 구문을 제공하며 각각 두 가지 특징이 있습니다.
- 컨테이너 내용이 명시적으로 나열되거나
- 이해라고 하는 루핑 및 필터링 명령 세트를 통해 계산됩니다.
컴프리헨션의 일반적인 구문 요소는 다음과 같습니다.
comprehension ::= assignment_expression comp_for
comp_for ::= ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" or_test [comp_iter]
내포는 하나 이상의 for 절과 0개 이상의 for 또는 if 절이 뒤따르는 단일 표현식으로 구성됩니다. 이 경우 새 컨테이너의 요소는 각 for 또는 if 절을 블록으로 간주하고 왼쪽에서 오른쪽으로 중첩하고 가장 안쪽 블록에 도달할 때마다 요소를 생성하는 표현식을 평가하여 생성되는 요소입니다.
그러나 가장 왼쪽 for 절의 iterable 표현식을 제외하고 내포는 별도의 암시적으로 중첩된 범위에서 실행됩니다. 이렇게 하면 대상 목록에 할당된 이름이 둘러싸는 범위로 “누설”되지 않습니다.
가장 왼쪽 for 절의 iterable 표현식은 바깥쪽 범위에서 직접 평가된 다음 암시적으로 중첩된 범위에 인수로 전달됩니다. 후속 for 절과 가장 왼쪽 for 절의 필터 조건은 가장 왼쪽 iterable에서 얻은 값에 따라 달라질 수 있으므로 둘러싸는 범위에서 평가할 수 없습니다. 예: [범위(x, x+10)의 y에 대한 범위(10)의 x에 대한 x*y].
이해를 통해 항상 적절한 유형의 컨테이너가 생성되도록 하려면 암시적으로 중첩된 범위에서 표현식의 yield 및 yield가 금지됩니다.
Python 3.6부터 async def 함수에서 async for 절을 사용하여 비동기 이터레이터를 반복할 수 있습니다. async def 함수의 컴프리헨션은 선행 표현식 뒤에 오는 for 또는 async for 절로 구성될 수 있고 추가 for 또는 async for 절을 포함할 수 있으며 await 표현식을 사용할 수도 있습니다. 컴프리헨션에 async for 절이나 await 표현식 또는 기타 비동기 컴프리헨션이 포함되어 있으면 이를 비동기 컴프리헨션이라고 합니다. 비동기 이해는 나타나는 코루틴 함수의 실행을 일시 중단할 수 있습니다. PEP 530도 참조하십시오.
버전 3.6의 새로운 기능: 비동기 이해가 도입되었습니다.
버전 3.8에서 변경: 암시적으로 중첩된 범위에서 yield 및 yield from 금지.
버전 3.11에서 변경: 이제 비동기 함수의 이해 내에서 비동기 이해가 허용됩니다. 외부 이해는 암시적으로 비동기화됩니다.
6.2.5. List displays
목록 표시는 대괄호로 묶인 비어 있는 일련의 표현식입니다.
list_display ::= "[" [starred_list | comprehension] "]"
목록 표시는 새 목록 개체를 생성하며 내용은 식 목록 또는 이해에 의해 지정됩니다. 쉼표로 구분된 표현식 목록이 제공되면 해당 요소는 왼쪽에서 오른쪽으로 평가되고 해당 순서대로 목록 객체에 배치됩니다. Comprehension이 제공되면 목록은 Comprehension의 결과 요소로 구성됩니다.
6.2.6. Set displays
집합 디스플레이는 중괄호로 표시되며 키와 값을 구분하는 콜론이 없다는 점에서 사전 디스플레이와 구분됩니다.
set_display ::= "{" (starred_list | comprehension) "}"
집합 표시는 새로운 변경 가능한 집합 개체를 생성하며 내용은 일련의 표현식 또는 이해에 의해 지정됩니다. 쉼표로 구분된 표현식 목록이 제공되면 해당 요소가 왼쪽에서 오른쪽으로 평가되고 집합 개체에 추가됩니다. 컴프리헨션이 제공되면 컴프리헨션의 결과 요소로 집합이 구성됩니다.
빈 set는 {}로 생성할 수 없습니다. 이 리터럴은 빈 dictionary을 구성합니다.
6.2.7. Dictionary displays
사전 표시는 중괄호로 묶인 빈 일련의 키/데이텀 쌍일 수 있습니다.
dict_display ::= "{" [key_datum_list | dict_comprehension] "}"
key_datum_list ::= key_datum ("," key_datum)* [","]
key_datum ::= expression ":" expression | "**" or_expr
dict_comprehension ::= expression ":" expression comp_for
사전 표시는 새 사전 개체를 생성합니다.
키/데이터 쌍의 쉼표로 구분된 시퀀스가 제공되면 사전의 항목을 정의하기 위해 왼쪽에서 오른쪽으로 평가됩니다. 각 키 객체는 해당 데이터를 저장하기 위해 사전에 대한 키로 사용됩니다. 즉, 키/데이텀 목록에서 동일한 키를 여러 번 지정할 수 있으며 해당 키에 대한 최종 사전 값은 마지막으로 지정된 값이 됩니다.
이중 별표 **는 사전 압축 풀기를 나타냅니다. 해당 피연산자는 매핑이어야 합니다. 각 매핑 항목이 새 사전에 추가됩니다. 이후 값은 이전 키/데이텀 쌍 및 이전 사전 압축 풀기에 의해 이미 설정된 값을 대체합니다.
버전 3.5의 새로운 기능: 원래 PEP 448에서 제안한 사전 표시로 압축 풀기.
list 및 set comprehension과 달리 dict comprehension은 일반적인 “for” 및 “if” 절이 뒤에 오는 콜론으로 구분된 두 개의 표현식이 필요합니다. Comprehension이 실행되면 결과 키 및 값 요소가 생성된 순서대로 새 사전에 삽입됩니다.
키 값의 유형에 대한 제한 사항은 앞부분의 표준 유형 계층 구조 섹션에 나열되어 있습니다. (요약하면 키 유형은 해시 가능해야 하며 변경 가능한 모든 객체를 제외합니다.) 중복 키 간의 충돌은 감지되지 않습니다. 주어진 키 값에 대해 저장된 마지막 데이텀(디스플레이에서 가장 오른쪽에 있는 텍스트)이 우선합니다.
버전 3.8에서 변경: Python 3.8 이전에는 dict 컴프리헨션에서 키와 값의 평가 순서가 잘 정의되지 않았습니다. CPython에서 값은 키보다 먼저 평가되었습니다. 3.8부터는 PEP 572에서 제안한 대로 키가 값보다 먼저 평가됩니다.
6.2.8. Generator expressions
제너레이터 표현식은 괄호로 묶인 간결한 제너레이터 표기법입니다.
generator_expression ::= "(" expression comp_for ")"
제너레이터 표현식은 새로운 제너레이터 객체를 생성합니다. 구문은 대괄호나 중괄호 대신 괄호로 묶인다는 점을 제외하고 컴프리헨션과 동일합니다.
제너레이터 표현식에 사용된 변수는 제너레이터 객체에 대해 __next__() 메서드가 호출될 때 느리게 평가됩니다(일반 제너레이터와 동일한 방식으로). 그러나 가장 왼쪽 for 절의 iterable 표현식은 즉시 평가되므로 이로 인해 생성된 오류는 첫 번째 값이 검색된 지점이 아니라 생성기 표현식이 정의된 지점에서 방출됩니다. 후속 for 절과 가장 왼쪽 for 절의 필터 조건은 가장 왼쪽 iterable에서 얻은 값에 따라 달라질 수 있으므로 둘러싸는 범위에서 평가할 수 없습니다. 예: (범위(x, x+10)의 y에 대한 범위(10)의 x에 대한 x*y).
인수가 하나만 있는 호출에서는 괄호를 생략할 수 있습니다. 자세한 내용은 호출 섹션을 참조하십시오.
생성기 표현식 자체의 예상 작동을 방해하지 않기 위해 암시적으로 정의된 생성기에서 표현식의 yield 및 yield가 금지됩니다.
생성기 표현식에 async for 절 또는 await 표현식이 포함된 경우 이를 비동기 생성기 표현식이라고 합니다. 비동기 제너레이터 표현식은 비동기 이터레이터인 새 비동기 제너레이터 객체를 반환합니다(비동기 이터레이터 참조).
버전 3.6의 새로운 기능: 비동기 생성기 표현식이 도입되었습니다.
버전 3.7에서 변경: Python 3.7 이전에는 비동기 생성기 표현식이 async def 코루틴에만 나타날 수 있었습니다. 3.7부터 모든 함수는 비동기 생성기 표현식을 사용할 수 있습니다.
버전 3.8에서 변경: 암시적으로 중첩된 범위에서 yield 및 yield from 금지.
6.2.9. Yield expressions
yield_atom ::= "(" yield_expression ")"
yield_expression ::= "yield" [expression_list | "from" expression]
yield 표현식은 generator 함수 또는 asynchronous generator 함수를 정의할 때 사용되므로 함수 정의의 본문에서만 사용할 수 있습니다. 함수 본문에서 yield 표현식을 사용하면 해당 함수가 생성기 함수가 되고 async def 함수의 본문에서 사용하면 해당 코루틴 함수가 비동기 생성기 함수가 됩니다. 예를 들어:
def gen(): # defines a generator function
yield 123
async def agen(): # defines an asynchronous generator function
yield 123
포함 범위에 대한 부작용으로 인해 이해 및 생성기 표현식을 구현하는 데 사용되는 암시적으로 정의된 범위의 일부로 yield 표현식이 허용되지 않습니다.
버전 3.8에서 변경: 컴프리헨션 및 제너레이터 표현식을 구현하는 데 사용되는 암시적으로 중첩된 범위에서 Yield 표현식이 금지됩니다.
생성기 기능은 아래에 설명되어 있으며 비동기식 생성기 기능은 비동기식 생성기 기능 섹션에서 별도로 설명합니다.
제너레이터 함수가 호출되면 제너레이터라고 하는 이터레이터를 반환합니다. 그런 다음 해당 생성기가 생성기 기능의 실행을 제어합니다. 생성기의 메서드 중 하나가 호출되면 실행이 시작됩니다. 그 때 실행은 첫 번째 yield 표현식으로 진행되며 여기서 다시 일시 중단되어 expression_list의 값을 생성기의 호출자에게 반환하거나 expression_list가 생략된 경우 None을 반환합니다. 일시 중단이란 로컬 변수의 현재 바인딩, 명령 포인터, 내부 평가 스택 및 모든 예외 처리 상태를 포함하여 모든 로컬 상태가 유지됨을 의미합니다. 생성기의 메서드 중 하나를 호출하여 실행을 재개하면 함수는 yield 표현식이 또 다른 외부 호출인 것처럼 정확하게 진행할 수 있습니다. 재개 후 yield 표현식의 값은 실행을 재개한 메서드에 따라 다릅니다. __next__()가 사용되면(일반적으로 for 또는 next() 내장을 통해) 결과는 None입니다. 그렇지 않고 send()를 사용하면 결과는 해당 메서드에 전달된 값이 됩니다.
이 모든 것이 생성기 기능을 코루틴과 매우 유사하게 만듭니다. 여러 번 양보하고 진입점이 두 개 이상 있으며 실행이 일시 중지될 수 있습니다. 유일한 차이점은 제너레이터 함수는 yield 후에 실행이 계속되어야 하는 위치를 제어할 수 없다는 것입니다. 제어는 항상 제너레이터의 호출자에게 전달됩니다.
yield 표현식은 try 구성의 모든 위치에서 허용됩니다. 제너레이터가 종료되기 전에 재개되지 않으면(0 참조 카운트에 도달하거나 가비지 수집됨으로써), 제너레이터-이터레이터의 close() 메서드가 호출되어 계류 중인 모든 finally 절이 실행될 수 있습니다.
의 yield를 사용하는 경우 제공된 표현식은 이터러블이어야 합니다. iterable을 반복하여 생성된 값은 현재 생성기 메서드의 호출자에게 직접 전달됩니다. send()로 전달된 모든 값과 throw()로 전달된 모든 예외는 적절한 메서드가 있는 경우 기본 반복자에게 전달됩니다. 그렇지 않은 경우 send()는 AttributeError 또는 TypeError를 발생시키는 반면 throw()는 전달된 예외를 즉시 발생시킵니다.
기본 반복자가 완료되면 발생한 StopIteration 인스턴스의 값 속성이 yield 표현식의 값이 됩니다. StopIteration을 발생시킬 때 명시적으로 설정하거나 하위 반복자가 생성기일 때 자동으로 설정될 수 있습니다(하위 생성기에서 값을 반환하여).
버전 3.3에서 변경: 제어 흐름을 하위 반복자에게 위임하기 위해 의 yield를 추가했습니다.
대입문 오른쪽에 yield 표현식이 유일한 표현식인 경우 괄호를 생략할 수 있습니다.
See also
PEP 255 – Simple Generators
Python에 생성기 및 yield 문을 추가하기 위한 제안.
PEP 342 – Coroutines via Enhanced Generators
API 및 생성기 구문을 개선하여 간단한 코루틴으로 사용할 수 있도록 제안합니다.
PEP 380 – Syntax for Delegating to a Subgenerator
하위 생성자에게 쉽게 위임할 수 있도록 yield_from 구문을 도입하자는 제안.
PEP 525 – Asynchronous Generators
코루틴 함수에 생성기 기능을 추가하여 PEP 492에서 확장된 제안입니다.
6.2.9.1. Generator-iterator methods
이 하위 섹션에서는 생성기 반복자의 메서드를 설명합니다. 생성기 기능의 실행을 제어하는 데 사용할 수 있습니다.
제너레이터가 이미 실행 중일 때 아래 제너레이터 메서드를 호출하면 ValueError 예외가 발생합니다.
generator.__next__()
생성기 함수의 실행을 시작하거나 마지막으로 실행된 yield 표현식에서 다시 시작합니다. 제너레이터 함수가 __next__() 메서드로 재개되면 현재 yield 표현식은 항상 None으로 평가됩니다. 그런 다음 실행은 다음 yield 표현식으로 계속되며 여기서 생성기는 다시 일시 중지되고 expression_list의 값은 __next__()의 호출자에게 반환됩니다. 생성기가 다른 값을 생성하지 않고 종료하면 StopIteration 예외가 발생합니다.
이 메서드는 일반적으로 암시적으로 호출됩니다. for 루프 또는 내장 next() 함수를 통해.
generator.send(value)
실행을 재개하고 생성기 함수에 값을 “전송”합니다. value 인수는 현재 yield 표현식의 결과가 됩니다. send() 메서드는 생성기가 생성한 다음 값을 반환하거나, 생성기가 다른 값을 생성하지 않고 종료하는 경우 StopIteration을 발생시킵니다. 제너레이터를 시작하기 위해 send()를 호출할 때 값을 받을 수 있는 yield 표현식이 없기 때문에 None을 인수로 하여 호출해야 합니다.
generator.throw(value)
generator.throw(type[, value[, traceback]])
제너레이터가 일시 중지된 지점에서 예외를 발생시키고 제너레이터 함수가 생성한 다음 값을 반환합니다. 생성기가 다른 값을 생성하지 않고 종료하면 StopIteration 예외가 발생합니다. 생성기 함수가 전달된 예외를 포착하지 않거나 다른 예외를 발생시키면 해당 예외가 호출자에게 전파됩니다.
일반적인 사용에서 이것은 raise 키워드가 사용되는 방식과 유사한 단일 예외 인스턴스로 호출됩니다.
그러나 이전 버전과의 호환성을 위해 이전 버전 Python의 규칙에 따라 두 번째 서명이 지원됩니다. type 인수는 예외 클래스여야 하고 value는 예외 인스턴스여야 합니다. 값이 제공되지 않으면 유형 생성자가 호출되어 인스턴스를 가져옵니다. 트레이스백이 제공되면 예외에 설정됩니다. 그렇지 않으면 값에 저장된 기존 __traceback__ 속성이 지워질 수 있습니다.
generator.close()
생성기 함수가 일시 중지된 지점에서 GeneratorExit를 발생시킵니다. 그런 다음 제너레이터 함수가 정상적으로 종료하거나 이미 닫혀 있거나 GeneratorExit(예외를 포착하지 않음으로써)를 발생시키면 close가 호출자에게 반환됩니다. 생성기가 값을 생성하면 RuntimeError가 발생합니다. 생성기가 다른 예외를 발생시키면 호출자에게 전파됩니다. close()는 제너레이터가 예외 또는 정상적인 종료로 인해 이미 종료된 경우 아무 작업도 수행하지 않습니다.
6.2.9.2. Examples
다음은 제너레이터와 제너레이터 함수의 동작을 보여주는 간단한 예입니다.
>>> def echo(value=None):
... print("Execution starts when 'next()' is called for the first time.")
... try:
... while True:
... try:
... value = (yield value)
... except Exception as e:
... value = e
... finally:
... print("Don't forget to clean up when 'close()' is called.")
...
>>> generator = echo(1)
>>> print(next(generator))
... Execution starts when 'next()' is called for the first time.
... 1
>>> print(next(generator))
... None
>>> print(generator.send(2))
... 2
>>> generator.throw(TypeError, "spam")
... TypeError('spam',)
>>> generator.close()
... Don't forget to clean up when 'close()' is called.
yield from을 사용하는 예는 “Python의 새로운 기능”에서 PEP 380: 하위 생성기에 위임하는 구문을 참조하세요.
6.2.9.3. Asynchronous generator functions
async def를 사용하여 정의된 함수 또는 메서드에 yield 표현식이 있으면 함수를 비동기 생성기 함수로 추가로 정의합니다.
비동기 제너레이터 함수가 호출되면 비동기 제너레이터 객체로 알려진 비동기 이터레이터를 반환합니다. 그런 다음 해당 개체는 생성기 함수의 실행을 제어합니다. 비동기 제너레이터 객체는 일반적으로 제너레이터 객체가 for 문에서 사용되는 방식과 유사하게 코루틴 함수의 async for 문에서 사용됩니다.
비동기 생성기의 메서드 중 하나를 호출하면 어웨이터블 객체가 반환되고 이 객체가 어웨이트되면 실행이 시작됩니다. 이때 실행은 첫 번째 yield 표현식으로 진행되며 여기서 다시 일시 중단되어 대기 중인 코루틴에 expression_list 값을 반환합니다. 제너레이터와 마찬가지로 일시 중단은 로컬 변수의 현재 바인딩, 명령 포인터, 내부 평가 스택 및 모든 예외 처리 상태를 포함하여 모든 로컬 상태가 유지됨을 의미합니다. 비동기 생성기의 메서드가 반환한 다음 개체를 기다리면서 실행이 재개되면 함수는 yield 표현식이 또 다른 외부 호출인 것처럼 정확하게 진행할 수 있습니다. 재개 후 yield 표현식의 값은 실행을 재개한 메서드에 따라 다릅니다. __anext__()가 사용되면 결과는 None입니다. 그렇지 않고 asend()가 사용되면 결과는 해당 메서드에 전달된 값이 됩니다.
비동기 제너레이터가 중단, 호출자 작업 취소 또는 기타 예외로 인해 조기에 종료되는 경우, 제너레이터의 비동기 정리 코드가 실행되어 예상하지 못한 컨텍스트에서 예외를 발생시키거나 컨텍스트 변수에 액세스할 수 있습니다. 또는 async-generator 가비지 수집 후크가 호출될 때 이벤트 루프가 종료되는 동안. 이를 방지하려면 호출자는 aclose() 메서드를 호출하여 생성기를 종료하고 궁극적으로 이벤트 루프에서 분리함으로써 비동기 생성기를 명시적으로 닫아야 합니다.
비동기 생성기 함수에서 yield 표현식은 try 구성의 모든 위치에서 허용됩니다. 그러나 비동기 생성기가 완료되기 전에 재개되지 않으면(0 참조 횟수에 도달하거나 가비지 수집됨) try 구문 내의 yield 표현식이 보류 중인 finally 절을 실행하지 못할 수 있습니다. 이 경우 비동기 제너레이터를 실행하는 이벤트 루프 또는 스케줄러는 비동기 제너레이터-이터레이터의 aclose() 메서드를 호출하고 결과 코루틴 객체를 실행하여 보류 중인 모든 finally 절을 실행할 수 있도록 합니다.
이벤트 루프 종료 시 종료를 처리하려면 이벤트 루프는 비동기 생성기 반복자를 사용하고 아마도 aclose()를 호출하고 코루틴을 실행하는 종료자 함수를 정의해야 합니다. 이 파이널라이저는 sys.set_asyncgen_hooks()를 호출하여 등록할 수 있습니다. 처음 반복할 때 비동기 생성기 반복자는 종료 시 호출할 등록된 종료자를 저장합니다. 종료자 메서드의 참조 예제는 Lib/asyncio/base_events.py에서 asyncio.Loop.shutdown_asyncgens 구현을 참조하세요.
의 yield 표현식은 비동기 생성기 함수에서 사용될 때 구문 오류입니다.
6.2.9.4. Asynchronous generator-iterator methods
이 하위 섹션에서는 생성기 함수의 실행을 제어하는 데 사용되는 비동기 생성기 반복자의 메서드를 설명합니다.
coroutine agen.__anext__()
run이 비동기 생성기를 실행하기 시작하거나 마지막으로 실행된 yield 표현식에서 다시 시작하는 awaitable을 반환합니다. 비동기 생성기 함수가 __anext__() 메서드로 재개되면 현재 yield 표현식은 반환된 awaitable에서 항상 None으로 평가되며, 실행 시 다음 yield 표현식으로 계속됩니다. yield 표현식의 expression_list 값은 완료 코루틴에 의해 발생한 StopIteration 예외 값입니다. 비동기 제너레이터가 다른 값을 생성하지 않고 종료되면 awaitable은 대신 StopAsyncIteration 예외를 발생시켜 비동기 반복이 완료되었음을 알립니다.
이 메서드는 일반적으로 async for 루프에 의해 암시적으로 호출됩니다.
coroutine agen.asend(value)
실행 시 비동기 생성기의 실행을 재개하는 어웨이터블을 반환합니다. 제너레이터의 send() 메서드와 마찬가지로 비동기 제너레이터 함수로 값을 “보내고” value 인수는 현재 yield 표현식의 결과가 됩니다. asend() 메서드에 의해 반환된 어웨이터블은 발생한 StopIteration의 값으로 생성기가 생성한 다음 값을 반환하거나, 비동기 생성기가 다른 값을 생성하지 않고 종료하는 경우 StopAsyncIteration을 발생시킵니다. 비동기 생성기를 시작하기 위해 asend()를 호출할 때 값을 받을 수 있는 yield 표현식이 없기 때문에 None을 인수로 사용하여 호출해야 합니다.
coroutine agen.athrow(type[, value[, traceback]])
비동기 제너레이터가 일시 중지된 지점에서 유형 유형의 예외를 발생시키는 어웨이터블을 반환하고 발생한 StopIteration 예외의 값으로 생성기 함수가 생성한 다음 값을 반환합니다. 비동기 제너레이터가 다른 값을 생성하지 않고 종료되면 StopAsyncIteration 예외가 awaitable에 의해 발생합니다. 생성기 함수가 전달된 예외를 포착하지 않거나 다른 예외를 발생시키는 경우 awaitable이 실행될 때 해당 예외가 awaitable의 호출자에게 전파됩니다.
coroutine agen.aclose()
실행 시 일시 중지된 지점에서 비동기 제너레이터 함수로 GeneratorExit를 발생시키는 어웨이터블을 반환합니다. 비동기 제너레이터 함수가 정상적으로 종료하거나 이미 닫혀 있거나 GeneratorExit를 발생시키면(예외를 포착하지 않음으로써) 반환된 어웨이터블이 StopIteration 예외를 발생시킵니다. 비동기 생성기에 대한 후속 호출에서 반환된 추가 대기 가능 항목은 StopAsyncIteration 예외를 발생시킵니다. 비동기 제너레이터가 값을 생성하면 awaitable에 의해 RuntimeError가 발생합니다. 비동기 제너레이터가 다른 예외를 발생시키면 어웨이터블 호출자에게 전파됩니다. 비동기 생성기가 예외 또는 정상적인 종료로 인해 이미 종료된 경우 aclose()에 대한 추가 호출은 아무 작업도 수행하지 않는 awaitable을 반환합니다.
6.3. Primaries
기본은 언어의 가장 밀접하게 바인딩된 작업을 나타냅니다. 구문은 다음과 같습니다.
primary ::= atom | attributeref | subscription | slicing | call
6.3.1. Attribute references
속성 참조는 기본 뒤에 마침표와 이름이 오는 것입니다.
attributeref ::= primary "." identifier
기본적으로 대부분의 객체가 수행하는 속성 참조를 지원하는 유형의 객체로 평가되어야 합니다. 그런 다음 이 객체는 이름이 식별자인 속성을 생성하도록 요청받습니다. 이 프로덕션은 __getattr__() 메서드를 재정의하여 사용자 정의할 수 있습니다. 이 속성을 사용할 수 없으면 AttributeError 예외가 발생합니다. 그렇지 않으면 생성된 개체의 유형과 값이 개체에 의해 결정됩니다. 동일한 속성 참조를 여러 번 평가하면 다른 개체가 생성될 수 있습니다.
6.3.2. Subscriptions
컨테이너 클래스 인스턴스의 구독은 일반적으로 컨테이너에서 요소를 선택합니다. 제네릭 클래스의 구독은 일반적으로 GenericAlias 개체를 반환합니다.
subscription ::= primary "[" expression_list "]"
객체가 아래 첨자일 때 인터프리터는 기본 및 표현식 목록을 평가합니다.
기본은 구독을 지원하는 개체로 평가되어야 합니다. 객체는 __getitem__() 및 __class_getitem__() 중 하나 또는 둘 다를 정의하여 구독을 지원할 수 있습니다. 기본이 아래 첨자인 경우 식 목록의 평가 결과가 이러한 메서드 중 하나로 전달됩니다. __getitem__ 대신 __class_getitem__이 호출되는 경우에 대한 자세한 내용은 __class_getitem__ 대 __getitem__을 참조하십시오.
식 목록에 하나 이상의 쉼표가 포함되어 있으면 식 목록의 항목을 포함하는 튜플로 평가됩니다. 그렇지 않으면 표현식 목록은 목록의 유일한 구성원 값으로 평가됩니다.
내장 객체의 경우 __getitem__()을 통해 구독을 지원하는 두 가지 유형의 객체가 있습니다:
- Mappings. 기본이 매핑인 경우 식 목록은 값이 매핑의 키 중 하나인 개체로 평가되어야 하며 구독은 해당 키에 해당하는 매핑의 값을 선택합니다. 내장 매핑 클래스의 예는 dict 클래스입니다.
- Sequences. 기본이 시퀀스인 경우 식 목록은 int 또는 슬라이스로 평가되어야 합니다(다음 섹션에서 설명). 내장 시퀀스 클래스의 예로는 str, list 및 tuple 클래스가 있습니다.
공식 구문은 시퀀스의 음수 인덱스에 대해 특별한 규정을 만들지 않습니다. 그러나 내장 시퀀스는 모두 예를 들어 x[-1]이 x의 마지막 항목을 선택하도록 인덱스에 시퀀스의 길이를 추가하여 음수 인덱스를 해석하는 __getitem__() 메서드를 제공합니다. 결과 값은 시퀀스의 항목 수보다 작은 음이 아닌 정수여야 하며 구독은 색인이 해당 값(0부터 계산)인 항목을 선택합니다. 음수 인덱스 및 슬라이싱에 대한 지원은 객체의 __getitem__() 메서드에서 발생하므로 이 메서드를 재정의하는 하위 클래스는 해당 지원을 명시적으로 추가해야 합니다.
문자열은 항목이 문자인 특별한 종류의 시퀀스입니다. 문자는 별도의 데이터 유형이 아니라 정확히 한 문자의 문자열입니다.
6.3.3. Slicings
슬라이싱은 시퀀스 객체(예: 문자열, 튜플 또는 목록)의 항목 범위를 선택합니다. 슬라이싱은 식으로 사용되거나 대입문 또는 del 문에서 대상으로 사용될 수 있습니다. 슬라이싱 구문:
slicing ::= primary "[" slice_list "]"
slice_list ::= slice_item ("," slice_item)* [","]
slice_item ::= expression | proper_slice
proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression
여기에는 공식 구문에 모호성이 있습니다. 표현식 목록처럼 보이는 모든 것이 슬라이스 목록처럼 보이기 때문에 모든 구독은 슬라이싱으로 해석될 수 있습니다. 구문을 더 복잡하게 만드는 대신, 이 경우 구독으로 해석하는 것이 슬라이싱으로 해석하는 것보다 우선한다고 정의함으로써 모호함이 해소됩니다(이는 슬라이스 목록에 적절한 슬라이스가 포함되지 않는 경우입니다).
슬라이싱의 의미 체계는 다음과 같습니다. 기본은 다음과 같이 슬라이스 목록에서 생성된 키로 인덱싱됩니다(일반 구독과 동일한 __getitem__() 메서드 사용). 조각 목록에 하나 이상의 쉼표가 포함된 경우 키는 조각 항목의 변환을 포함하는 튜플입니다. 그렇지 않으면 단일 조각 항목의 변환이 핵심입니다. 식인 조각 항목의 변환이 해당 식입니다. 적절한 슬라이스의 변환은 슬라이스 객체(표준 유형 계층 섹션 참조)이며 그의 시작, 중지 및 단계 속성은 각각 하한, 상한 및 보폭으로 지정된 표현식의 값이며 누락된 표현식을 None으로 대체합니다.
6.3.4. Calls
호출은 아마도 비어 있는 일련의 인수를 사용하여 호출 가능한 객체(예: 함수)를 호출합니다.
call ::= primary "(" [argument_list [","] | comprehension] ")"
argument_list ::= positional_arguments ["," starred_and_keywords]
["," keywords_arguments]
| starred_and_keywords ["," keywords_arguments]
| keywords_arguments
positional_arguments ::= positional_item ("," positional_item)*
positional_item ::= assignment_expression | "*" expression
starred_and_keywords ::= ("*" expression | keyword_item)
("," "*" expression | "," keyword_item)*
keywords_arguments ::= (keyword_item | "**" expression)
("," keyword_item | "," "**" expression)*
keyword_item ::= identifier "=" expression
선택적 후행 쉼표는 위치 및 키워드 인수 뒤에 나타날 수 있지만 의미 체계에는 영향을 미치지 않습니다.
기본은 호출 가능한 객체로 평가되어야 합니다(사용자 정의 함수, 내장 함수, 내장 객체의 메서드, 클래스 객체, 클래스 인스턴스의 메서드 및 __call__() 메서드가 있는 모든 객체는 호출 가능합니다). 호출이 시도되기 전에 모든 인수 표현식이 평가됩니다. 공식 매개변수 목록의 구문은 함수 정의 섹션을 참조하십시오.
키워드 인수가 있으면 먼저 다음과 같이 위치 인수로 변환됩니다. 먼저 정규 매개변수에 대해 채워지지 않은 슬롯 목록이 생성됩니다. N개의 위치 인수가 있는 경우 첫 번째 N개의 슬롯에 배치됩니다. 다음으로 각 키워드 인수에 대해 식별자를 사용하여 해당 슬롯을 결정합니다(식별자가 첫 번째 형식 매개변수 이름과 동일한 경우 첫 번째 슬롯이 사용되는 식). 슬롯이 이미 채워져 있으면 TypeError 예외가 발생합니다. 그렇지 않으면 인수가 슬롯에 배치되어 슬롯을 채웁니다(표현식이 None인 경우에도 슬롯을 채웁니다). 모든 인수가 처리되면 아직 채워지지 않은 슬롯이 함수 정의의 해당 기본값으로 채워집니다. (디폴트는 함수가 정의될 때 한 번 계산되므로 리스트나 딕셔너리와 같은 가변 객체가 디폴트 값으로 사용되면 해당 슬롯에 대한 인수 값을 지정하지 않는 모든 호출이 공유하게 됩니다. 일반적으로 피해야 합니다.) 기본값이 지정되지 않은 채워지지 않은 슬롯이 있으면 TypeError 예외가 발생합니다. 그렇지 않으면 채워진 슬롯 목록이 호출의 인수 목록으로 사용됩니다.
CPython 구현 세부 정보: 구현은 위치 매개변수에 이름이 없는 내장 함수를 제공할 수 있습니다. 문서화 목적으로 ‘이름이 지정’되어 키워드로 제공될 수 없는 경우에도 마찬가지입니다. CPython에서 이는 인수를 구문 분석하기 위해 PyArg_ParseTuple()을 사용하는 C로 구현된 함수의 경우입니다.
형식 매개변수 슬롯보다 더 많은 위치 인수가 있는 경우 *identifier 구문을 사용하는 형식 매개변수가 존재하지 않는 한 TypeError 예외가 발생합니다. 이 경우 형식 매개변수는 초과 위치 인수를 포함하는 튜플(또는 초과 위치 인수가 없는 경우 빈 튜플)을 받습니다.
키워드 인수가 공식 매개변수 이름에 해당하지 않는 경우 **식별자 구문을 사용하는 공식 매개변수가 존재하지 않는 한 TypeError 예외가 발생합니다. 이 경우 형식 매개변수는 초과 키워드 인수(키워드를 키로 사용하고 인수 값을 해당 값으로 사용)를 포함하는 사전을 수신하거나 초과 키워드 인수가 없는 경우 (새) 빈 사전을 수신합니다.
구문 *expression이 함수 호출에 나타나면 expression은 iterable로 평가되어야 합니다. 이러한 iterable의 요소는 추가 위치 인수인 것처럼 처리됩니다. 호출 f(x1, x2, *y, x3, x4)의 경우 y가 시퀀스 y1, …, yM으로 평가되면 이는 M+4 위치 인수 x1, x2, y1, …, yM을 사용한 호출과 동일합니다. , x3, x4.
그 결과 *expression 구문이 명시적 키워드 인수 뒤에 나타날 수 있지만 키워드 인수(및 **expression 인수 – 아래 참조)보다 먼저 처리됩니다. 그래서:
>>> def f(a, b):
... print(a, b)
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'a'
>>> f(1, *(2,))
1 2
키워드 인수와 *expression 구문이 동일한 호출에서 사용되는 경우는 드문 일이므로 실제로는 이러한 혼동이 자주 발생하지 않습니다.
구문 **expression이 함수 호출에 나타나면 expression은 매핑으로 평가되어야 하며 그 내용은 추가 키워드 인수로 처리됩니다. 키와 일치하는 매개변수에 이미 값이 주어진 경우(명시적 키워드 인수 또는 다른 압축 해제에서) TypeError 예외가 발생합니다.
**식을 사용하는 경우 이 매핑의 각 키는 문자열이어야 합니다. 매핑의 각 값은 이름이 키와 동일한 키워드 할당에 적합한 첫 번째 공식 매개변수에 할당됩니다. 키는 Python 식별자일 필요가 없습니다(예: “max-temp °F”는 허용되지만 선언할 수 있는 형식 매개변수와 일치하지 않음). 정식 매개변수와 일치하는 항목이 없으면 ** 매개변수에 의해 키-값 쌍이 수집됩니다. 일치하는 항목이 있거나 없으면 TypeError 예외가 발생합니다.
구문 *identifier 또는 **identifier를 사용하는 형식 매개변수는 위치 인수 슬롯이나 키워드 인수 이름으로 사용할 수 없습니다.
버전 3.5에서 변경: 함수 호출은 얼마든지 * 및 ** 압축 해제를 허용하고 위치 인수는 반복 가능한 압축 해제(*)를 따를 수 있으며 키워드 인수는 사전 압축 해제(**)를 따를 수 있습니다. 원래 PEP 448에서 제안했습니다.
예외가 발생하지 않는 한 호출은 항상 어떤 값을 반환합니다. None일 수 있습니다. 이 값이 계산되는 방식은 호출 가능 객체의 유형에 따라 다릅니다.
그렇다면—
사용자 정의 함수:
함수의 코드 블록이 실행되어 인수 목록에 전달됩니다. 코드 블록이 가장 먼저 하는 일은 공식 매개변수를 인수에 바인딩하는 것입니다. 이것은 함수 정의 섹션에 설명되어 있습니다. 코드 블록이 return 문을 실행할 때 함수 호출의 반환 값을 지정합니다.
내장 함수 또는 메소드:
결과는 통역사에게 달려 있습니다. 내장 함수 및 메소드에 대한 설명은 내장 함수를 참조하십시오.
클래스 개체:
해당 클래스의 새 인스턴스가 반환됩니다.
클래스 인스턴스 메서드:
호출의 인수 목록보다 하나 더 긴 인수 목록을 사용하여 해당 사용자 정의 함수가 호출됩니다. 인스턴스가 첫 번째 인수가 됩니다.
클래스 인스턴스:
클래스는 __call__() 메서드를 정의해야 합니다; 그러면 해당 메서드가 호출된 것과 같은 효과가 나타납니다.
6.4. Await expression
어웨이터블 객체에서 코루틴 실행을 일시 중단합니다. 코루틴 함수 내에서만 사용할 수 있습니다.
await_expr ::= "await" primary
버전 3.5의 새로운 기능.
6.5. The power operator
멱 연산자는 왼쪽에 있는 단항 연산자보다 더 단단히 묶습니다. 오른쪽에 있는 단항 연산자보다 덜 밀접하게 바인딩됩니다. 구문은 다음과 같습니다.
power ::= (await_expr | primary) ["**" u_expr]
따라서 괄호로 묶지 않은 거듭제곱 및 단항 연산자 시퀀스에서 연산자는 오른쪽에서 왼쪽으로 평가됩니다(피연산자에 대한 평가 순서를 제한하지 않음). -1**2는 -1이 됩니다.
거듭제곱 연산자는 내장 pow() 함수와 동일한 의미를 가지며, 두 개의 인수를 사용하여 호출할 때 왼쪽 인수를 오른쪽 인수의 거듭제곱으로 승산합니다. 숫자 인수는 먼저 공통 유형으로 변환되고 결과는 해당 유형입니다.
int 피연산자의 경우 결과는 두 번째 인수가 음수가 아닌 한 피연산자와 동일한 유형을 가집니다. 이 경우 모든 인수는 float로 변환되고 float 결과가 전달됩니다. 예를 들어 10**2는 100을 반환하지만 10**-2는 0.01을 반환합니다.
0.0을 음의 거듭제곱으로 올리면 ZeroDivisionError가 발생합니다. 음수를 분수 거듭제곱으로 올리면 복소수가 됩니다. (이전 버전에서는 ValueError가 발생했습니다.)
이 작업은 특별한 __pow__() 메서드를 사용하여 사용자 지정할 수 있습니다.
6.6. Unary arithmetic and bitwise operations
모든 단항 산술 및 비트 연산은 동일한 우선 순위를 갖습니다.
u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr
단항 -(빼기) 연산자는 숫자 인수의 부정을 산출합니다. 작업은 __neg__() 특수 메서드로 재정의할 수 있습니다.
단항 +(더하기) 연산자는 숫자 인수를 변경하지 않고 반환합니다. 작업은 __pos__() 특수 메서드로 재정의할 수 있습니다.
단항 ~(반전) 연산자는 정수 인수의 비트 반전을 산출합니다. x의 비트 반전은 -(x+1)로 정의됩니다. __invert__() 특수 메서드를 재정의하는 정수 또는 사용자 정의 객체에만 적용됩니다.
세 가지 경우 모두 인수에 적절한 유형이 없으면 TypeError 예외가 발생합니다.
6.7. Binary arithmetic operations
이진 산술 연산에는 기존의 우선 순위 수준이 있습니다. 이러한 작업 중 일부는 숫자가 아닌 특정 유형에도 적용됩니다. 전력 연산자를 제외하고 곱셈 연산자와 덧셈 연산자의 두 가지 수준만 있습니다.
m_expr ::= u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
m_expr "//" u_expr | m_expr "/" u_expr |
m_expr "%" u_expr
a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr
*(곱하기) 연산자는 인수의 곱을 산출합니다. 인수는 둘 다 숫자이거나 한 인수는 정수이고 다른 인수는 시퀀스여야 합니다. 전자의 경우 숫자를 공통 유형으로 변환한 다음 함께 곱합니다. 후자의 경우 시퀀스 반복이 수행됩니다. 음수 반복 요소는 빈 시퀀스를 생성합니다.
이 작업은 특별한 __mul__() 및 __rmul__() 메서드를 사용하여 사용자 지정할 수 있습니다.
@(at) 연산자는 행렬 곱셈에 사용하기 위한 것입니다. 어떤 내장 Python 유형도 이 연산자를 구현하지 않습니다.
버전 3.5의 새로운 기능.
/(나누기) 및 //(바닥 나눗셈) 연산자는 인수의 몫을 산출합니다. 숫자 인수는 먼저 공통 유형으로 변환됩니다. 정수를 나누면 부동 소수점이 생성되는 반면, 정수를 나누면 정수가 됩니다. 결과는 결과에 적용된 ‘floor’ 함수를 사용한 수학적 나눗셈의 결과입니다. 0으로 나누면 ZeroDivisionError 예외가 발생합니다.
이 작업은 특별한 __truediv__() 및 __floordiv__() 메서드를 사용하여 사용자 지정할 수 있습니다.
%(모듈로) 연산자는 첫 번째 인수를 두 번째 인수로 나눈 나머지를 산출합니다. 숫자 인수는 먼저 공통 유형으로 변환됩니다. 제로 오른쪽 인수는 ZeroDivisionError 예외를 발생시킵니다. 인수는 부동 소수점 숫자일 수 있습니다. 예를 들어 3.14%0.7은 0.34입니다(3.14는 4*0.7 + 0.34이므로). 결과의 절대값은 두 번째 피연산자 1의 절대값보다 엄격하게 작습니다.
바닥 나눗셈과 모듈로 연산자는 다음 항등식으로 연결됩니다. x == (x//y)*y + (x%y). 바닥 나눗셈과 모듈로는 내장 함수 divmod()와도 연결됩니다: divmod(x, y) == (x//y, x%y). 2.
숫자에 대해 모듈로 연산을 수행하는 것 외에도 % 연산자는 문자열 개체에 의해 오버로드되어 구식 문자열 서식 지정(보간이라고도 함)을 수행합니다. 문자열 포매팅 구문은 Python Library Reference, 섹션 printf-style String Formatting에 설명되어 있습니다.
모듈로 연산은 특별한 __mod__() 메서드를 사용하여 사용자 정의할 수 있습니다.
바닥 나누기 연산자, 모듈로 연산자 및 divmod() 함수는 복소수에 대해 정의되지 않습니다. 대신 적절한 경우 abs() 함수를 사용하여 부동 소수점 숫자로 변환합니다.
+(더하기) 연산자는 해당 인수의 합계를 산출합니다. 인수는 둘 다 숫자이거나 동일한 유형의 시퀀스여야 합니다. 전자의 경우 숫자를 공통 유형으로 변환한 다음 함께 더합니다. 후자의 경우 시퀀스가 연결됩니다.
이 작업은 특별한 __add__() 및 __radd__() 메서드를 사용하여 사용자 지정할 수 있습니다.
-(빼기) 연산자는 인수의 차이를 산출합니다. 숫자 인수는 먼저 공통 유형으로 변환됩니다.
이 작업은 특별한 __sub__() 메서드를 사용하여 사용자 정의할 수 있습니다.
6.8. Shifting operations
이동 연산은 산술 연산보다 우선 순위가 낮습니다.
shift_expr ::= a_expr | shift_expr ("<<" | ">>") a_expr
이러한 연산자는 정수를 인수로 허용합니다. 첫 번째 인수를 두 번째 인수에서 지정한 비트 수만큼 왼쪽 또는 오른쪽으로 이동합니다.
이 작업은 특별한 __lshift__() 및 __rshift__() 메서드를 사용하여 사용자 지정할 수 있습니다.
n비트 오른쪽 시프트는 pow(2,n)에 의한 플로어 분할로 정의됩니다. n 비트 왼쪽 시프트는 pow(2,n)과의 곱셈으로 정의됩니다.
6.9. Binary bitwise operations
세 가지 비트 연산은 각각 다른 우선 순위 수준을 갖습니다.
and_expr ::= shift_expr | and_expr "&" shift_expr
xor_expr ::= and_expr | xor_expr "^" and_expr
or_expr ::= xor_expr | or_expr "|" xor_expr
& 연산자는 인수의 비트별 AND를 생성하며, 이는 정수이거나 그 중 하나가 __and__() 또는 __rand__() 특수 메서드를 재정의하는 사용자 정의 객체여야 합니다.
^ 연산자는 정수이거나 그 중 하나가 __xor__() 또는 __rxor__() 특수 메서드를 재정의하는 사용자 정의 객체여야 하는 인수의 비트별 XOR(배타적 OR)을 생성합니다.
| 연산자는 정수이거나 그 중 하나가 __or__() 또는 __ror__() 특수 메서드를 재정의하는 사용자 정의 객체여야 하는 인수의 비트별(포함) OR을 생성합니다.
6.10. Comparisons
C와 달리 Python의 모든 비교 연산은 동일한 우선 순위를 가지므로 산술, 이동 또는 비트 연산보다 낮습니다. 또한 C와 달리 a < b < c와 같은 표현은 수학에서 관습적으로 해석됩니다.
comparison ::= or_expr (comp_operator or_expr)*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
비교 결과 부울 값(True 또는 False)이 생성됩니다. 사용자 지정 풍부한 비교 메서드는 부울이 아닌 값을 반환할 수 있습니다. 이 경우 Python은 부울 컨텍스트에서 해당 값에 대해 bool()을 호출합니다.
비교는 임의로 연결될 수 있습니다. 예를 들어 x < y <= z는 x < y 및 y <= z와 동일합니다. 단, y는 한 번만 평가됩니다(그러나 두 경우 모두 x < y가 발견될 때 z는 전혀 평가되지 않습니다) 거짓).
공식적으로 a, b, c, …, y, z가 표현식이고 op1, op2, …, opN이 비교 연산자인 경우 a op1 b op2 c … y opN z는 a op1 b 및 b op2 c와 동일합니다. 및 … y opN z, 단, 각 표현식은 최대 한 번만 평가됩니다.
a op1 b op2 c는 a와 c 사이의 어떤 종류의 비교도 의미하지 않으므로 예를 들어 x < y > z는 완벽하게 합법적입니다(예쁘지는 않지만).
6.10.1. Value comparisons
<, >, ==, >=, <= 및 != 연산자는 두 개체의 값을 비교합니다. 개체의 유형이 같을 필요는 없습니다.
개체, 값 및 유형 장에서는 개체에 값(유형 및 ID 외에)이 있음을 설명합니다. 객체의 값은 Python에서 다소 추상적인 개념입니다. 예를 들어 객체 값에 대한 표준 액세스 방법이 없습니다. 또한 객체의 값이 특정 방식으로 구성되어야 한다는 요구 사항도 없습니다. 모든 데이터 속성으로 구성됩니다. 비교 연산자는 개체의 값이 무엇인지에 대한 특정 개념을 구현합니다. 비교 구현을 통해 객체의 값을 간접적으로 정의하는 것으로 생각할 수 있습니다.
모든 유형은 object의 (직접 또는 간접) 하위 유형이므로 object에서 기본 비교 동작을 상속합니다. 유형은 기본 사용자 지정에 설명된 __lt__()와 같은 풍부한 비교 메서드를 구현하여 비교 동작을 사용자 지정할 수 있습니다.
같음 비교(== 및 !=)의 기본 동작은 개체의 ID를 기반으로 합니다. 따라서 동일한 ID를 가진 인스턴스의 동등 비교는 동등 결과를 낳고, 다른 ID를 가진 인스턴스의 동등 비교는 불평등 결과를 낳습니다. 이 기본 동작의 동기는 모든 객체가 반사적이어야 한다는 욕구입니다(즉, x는 y는 x == y를 암시합니다).
기본 순서 비교(<, >, <= 및 >=)는 제공되지 않습니다. 시도하면 TypeError가 발생합니다. 이 기본 동작에 대한 동기는 평등과 유사한 불변성이 부족하기 때문입니다.
서로 다른 ID를 가진 인스턴스가 항상 같지 않은 기본 같음 비교의 동작은 개체 값 및 값 기반 같음에 대한 합리적인 정의가 필요한 유형과 대조될 수 있습니다. 이러한 유형은 비교 동작을 사용자 정의해야 하며 실제로 많은 기본 제공 유형이 이를 수행했습니다.
다음 목록은 가장 중요한 기본 제공 유형의 비교 동작을 설명합니다.
- 기본 제공 숫자 유형(숫자 유형 – int, float, complex) 및 표준 라이브러리 유형 fractions.Fraction 및 decimal.Decimal의 숫자는 복소수가 순서 비교를 지원하지 않는다는 제한과 함께 유형 내에서 또는 유형 간에 비교할 수 있습니다. . 관련된 유형의 한계 내에서 정밀도 손실 없이 수학적으로(알고리즘적으로) 올바른지 비교합니다.
숫자가 아닌 값 float(‘NaN’) 및 decimal.Decimal(‘NaN’)은 특별합니다. 숫자와 숫자가 아닌 값의 순서 비교는 거짓입니다. 직관적이지 않은 의미는 숫자가 아닌 값이 자신과 같지 않다는 것입니다. 예를 들어 x = float(‘NaN’)인 경우 3 < x, x < 3 및 x == x는 모두 거짓이고 x != x는 참입니다. 이 동작은 IEEE 754를 준수합니다.
- None 및 NotImplemented는 싱글톤입니다. PEP 8은 싱글톤에 대한 비교는 항상 is 또는 is not으로 수행되어야 하며 결코 등호 연산자로 수행되어야 한다고 조언합니다.
- 이진 시퀀스(bytes 또는 bytearray의 인스턴스)는 유형 내에서 그리고 유형 간에 비교할 수 있습니다. 요소의 숫자 값을 사용하여 사전순으로 비교합니다.
- 문자열(str의 인스턴스)은 해당 문자의 숫자 유니코드 코드 포인트(내장 함수 ord()의 결과)를 사용하여 사전순으로 비교합니다. 삼
- 문자열과 이진 시퀀스는 직접 비교할 수 없습니다.
- 시퀀스(튜플, 목록 또는 범위의 인스턴스)는 각 유형 내에서만 비교할 수 있으며 범위는 순서 비교를 지원하지 않는다는 제한이 있습니다. 이러한 유형에 대한 동등 비교는 불평등을 초래하고 이러한 유형에 대한 순서 비교는 TypeError를 발생시킵니다.
시퀀스는 해당 요소의 비교를 사용하여 사전순으로 비교합니다. 기본 제공 컨테이너는 일반적으로 동일한 개체가 자신과 동일하다고 가정합니다. 이를 통해 성능을 개선하고 내부 불변성을 유지하기 위해 동일한 개체에 대한 동등성 테스트를 우회할 수 있습니다.
기본 제공 컬렉션 간의 사전식 비교는 다음과 같이 작동합니다.- 두 컬렉션이 같다고 비교되려면 같은 유형이어야 하고 길이도 같아야 하며 해당 요소의 각 쌍은 같은 것으로 비교되어야 합니다(예: [1,2] == (1,2)는 false입니다. 동일하지 않습니다).
- 순서 비교를 지원하는 컬렉션은 첫 번째 동일하지 않은 요소와 동일하게 정렬됩니다(예: [1,2,x] <= [1,2,y]는 x <= y와 동일한 값을 가짐). 해당 요소가 없으면 더 짧은 컬렉션이 먼저 정렬됩니다(예: [1,2] < [1,2,3]이 참임).
- 매핑(dict의 인스턴스)은 동일한(키, 값) 쌍이 있는 경우에만 동일한 것으로 비교됩니다. 키와 값의 동등 비교는 반사성을 적용합니다.
- 순서 비교(<, >, <= 및 >=)는 TypeError를 발생시킵니다.
집합(set 또는 frozenset의 인스턴스)은 유형 내에서 또는 유형 간에 비교할 수 있습니다.
하위 집합 및 상위 집합 테스트를 의미하는 순서 비교 연산자를 정의합니다. 이러한 관계는 전체 순서를 정의하지 않습니다(예를 들어, 두 집합 {1,2} 및 {2,3}은 동일하지 않으며, 서로의 하위 집합도, 서로의 상위 집합도 아닙니다). 따라서 집합은 전체 순서에 의존하는 함수에 대한 적절한 인수가 아닙니다(예를 들어 min(), max() 및 sorted()는 입력으로 집합 목록이 주어지면 정의되지 않은 결과를 생성함).
세트 비교는 해당 요소의 반사성을 강화합니다. - 대부분의 다른 기본 제공 유형에는 구현된 비교 메서드가 없으므로 기본 비교 동작을 상속합니다.
비교 동작을 사용자 지정하는 사용자 정의 클래스는 가능한 경우 몇 가지 일관성 규칙을 따라야 합니다.
- 평등 비교는 반사적이어야 합니다. 즉, 동일한 객체는 동등하게 비교되어야 합니다.
x is y
는x == y
를 의미합니다. - 비교는 대칭적이어야 합니다. 즉, 다음 표현식의 결과는 동일해야 합니다.
x == y
및y == x
x != y
및y != x
x < y
및y > x
x <= y
및y >= x
- 비교는 전이적이어야 합니다. 다음(완전하지 않은) 예는 다음을 설명합니다.
x > y
및y > z
는x > z
를 의미합니다.x < y
및y <= z
는x < z
를 의미합니다. - 역 비교 결과는 부울 부정이어야 합니다. 즉, 다음 표현식의 결과는 동일해야 합니다.
x == y
및x != y
아님x < y
및x >= y
아님(총 주문의 경우)x > y
및x <= y
아님(총 주문의 경우)
마지막 두 표현식은 전체적으로 정렬된 컬렉션에 적용됩니다(예: 시퀀스에 적용되지만 세트나 매핑에는 적용되지 않음). total_ordering() 데코레이터도 참조하십시오. - hash() 결과는 동등성과 일치해야 합니다. 동일한 객체는 동일한 해시 값을 가지거나 해시 불가로 표시되어야 합니다.
- Python은 이러한 일관성 규칙을 적용하지 않습니다. 실제로 숫자가 아닌 값은 이러한 규칙을 따르지 않는 예입니다.
Python은 이러한 일관성 규칙을 적용하지 않습니다. 실제로 숫자가 아닌 값은 이러한 규칙을 따르지 않는 예입니다.
6.10.2. Membership test operations
소속 여부를 테스트하는 연산자입니다. x in s는 x가 s의 구성원이면 True로 평가되고 그렇지 않으면 False로 평가됩니다. s에 없는 x는 s에 있는 x의 부정을 반환합니다. 모든 내장 시퀀스와 집합 유형은 사전뿐만 아니라 사전에 주어진 키가 있는지 여부를 테스트하는 사전을 지원합니다. list, tuple, set, frozenset, dict 또는 collections.deque와 같은 컨테이너 유형의 경우 x in y는 any(x is e 또는 x == e for e in y)와 동일합니다.
문자열 및 바이트 유형의 경우 y의 x는 x가 y의 하위 문자열인 경우에만 True입니다. 동등한 테스트는 y.find(x) != -1입니다. 빈 문자열은 항상 다른 문자열의 하위 문자열로 간주되므로 “abc”의 “”는 True를 반환합니다.
__contains__() 메서드를 정의하는 사용자 정의 클래스의 경우 y.__contains__(x)가 참 값을 반환하면 x in y는 True를 반환하고 그렇지 않으면 False를 반환합니다.
__contains__()를 정의하지 않지만 __iter__()를 정의하는 사용자 정의 클래스의 경우 x가 z이거나 x == z가 참인 일부 값 z가 y를 반복하는 동안 생성되는 경우 y의 x는 참입니다. . 반복 중에 예외가 발생하면 해당 예외가 발생한 것으로 간주됩니다.
마지막으로 이전 스타일의 반복 프로토콜이 시도됩니다. 클래스가 __getitem__()을 정의하는 경우 x가 y[i] 또는 x == y인 음이 아닌 정수 인덱스 i가 있는 경우에만 x in y는 True입니다. [i], 더 낮은 정수 인덱스가 없으면 IndexError 예외가 발생합니다. (다른 예외가 발생하면 해당 예외가 발생한 것과 같습니다.)
연산자 not in은 in의 역진실값을 갖도록 정의됩니다.
6.10.3. Identity comparisons
연산자는 개체의 ID를 테스트하거나 테스트하지 않습니다. x is y는 x와 y가 동일한 개체인 경우에만 참입니다. 객체의 ID는 id() 함수를 사용하여 결정됩니다. x is not y는 역 진리 값을 산출합니다.
6.11. Boolean operations
or_test ::= and_test | or_test "or" and_test
and_test ::= not_test | and_test "and" not_test
not_test ::= comparison | "not" not_test
부울 연산의 컨텍스트에서 그리고 제어 흐름 문에서 표현식을 사용하는 경우 다음 값은 false로 해석됩니다. False, None, 모든 유형의 숫자 0, 빈 문자열 및 컨테이너(문자열, 튜플, 목록, 사전 포함) , 세트 및 고정 세트). 다른 모든 값은 true로 해석됩니다. 사용자 정의 객체는 __bool__() 메서드를 제공하여 진리값을 사용자 정의할 수 있습니다.
연산자 not은 인수가 false이면 True를, 그렇지 않으면 False를 생성합니다.
x와 y 표현식은 먼저 x를 평가합니다. x가 false이면 해당 값이 반환됩니다. 그렇지 않으면 y가 평가되고 결과 값이 반환됩니다.
x 또는 y 표현식은 먼저 x를 평가합니다. x가 참이면 그 값이 반환됩니다. 그렇지 않으면 y가 평가되고 결과 값이 반환됩니다.
False 및 True로 반환하는 값과 유형을 제한하지 않고 마지막으로 평가된 인수를 반환합니다. 이것은 때때로 유용합니다. 예를 들어 s가 비어 있으면 기본값으로 대체되어야 하는 문자열인 경우 표현식 s 또는 ‘foo’는 원하는 값을 산출합니다. not은 새 값을 생성해야 하므로 인수 유형에 관계없이 부울 값을 반환합니다(예: not ‘foo’는 ”가 아닌 False를 생성합니다.).
6.12. Assignment expressions
assignment_expression ::= [identifier ":="] expression
할당 식(“명명된 식” 또는 “바다코끼리”라고도 함)은 식별자에 식을 할당하는 동시에 식 값을 반환합니다.
일반적인 사용 사례 중 하나는 일치하는 정규식을 처리하는 경우입니다.
if matching := pattern.search(data):
do_something(matching)
또는 청크로 파일 스트림을 처리할 때:
while chunk := file.read(9000):
process(chunk)
슬라이싱, 조건부, 람다, 키워드-인수 및 이해-if 식과 assert 및 with 문에서 하위 식으로 사용될 때 대입 식을 괄호로 묶어야 합니다. if 및 while 문을 포함하여 사용할 수 있는 다른 모든 위치에서는 괄호가 필요하지 않습니다.
버전 3.8의 새로운 기능: 할당 표현식에 대한 자세한 내용은 PEP 572를 참조하세요.
6.13. Conditional expressions
conditional_expression ::= or_test ["if" or_test "else" expression]
expression ::= conditional_expression | lambda_expr
조건식(“삼항 연산자”라고도 함)은 모든 Python 연산 중에서 우선 순위가 가장 낮습니다.
x if C else y 표현식은 x가 아닌 C라는 조건을 먼저 평가합니다. C가 참이면 x가 평가되고 그 값이 반환됩니다. 그렇지 않으면 y가 평가되고 해당 값이 반환됩니다.
조건식에 대한 자세한 내용은 PEP 308을 참조하십시오.
6.14. Lambdas
lambda_expr ::= "lambda" [parameter_list] ":" expression
람다 식(람다 형식이라고도 함)은 익명 함수를 만드는 데 사용됩니다. 표현식 lambda parameters: expression
은 함수 객체를 생성합니다. 명명되지 않은 개체는 다음으로 정의된 함수 개체처럼 동작합니다.
def <lambda>(parameters):
return expression
매개변수 목록의 구문에 대한 함수 정의 섹션을 참조하십시오. 람다 식으로 만든 함수는 문이나 주석을 포함할 수 없습니다.
6.15. Expression lists
expression_list ::= expression ("," expression)* [","]
starred_list ::= starred_item ("," starred_item)* [","]
starred_expression ::= expression | (starred_item ",")* [starred_item]
starred_item ::= assignment_expression | "*" or_expr
목록 또는 세트 표시의 일부인 경우를 제외하고 하나 이상의 쉼표를 포함하는 표현식 목록은 튜플을 생성합니다. 튜플의 길이는 목록에 있는 표현식의 수입니다. 표현식은 왼쪽에서 오른쪽으로 평가됩니다.
별표 *는 반복 가능한 압축 해제를 나타냅니다. 피연산자는 이터러블이어야 합니다. iterable은 언패킹 사이트에서 새 튜플, 목록 또는 집합에 포함되는 일련의 항목으로 확장됩니다.
버전 3.5의 새로운 기능: 원래 PEP 448에서 제안한 표현식 목록의 반복 가능한 압축 풀기.
후행 쉼표는 단일 튜플(a.k.a. 싱글톤)을 생성하는 데에만 필요합니다. 다른 모든 경우에는 선택 사항입니다. 후행 쉼표가 없는 단일 표현식은 튜플을 생성하지 않고 해당 표현식의 값을 생성합니다. (빈 튜플을 만들려면 빈 괄호 쌍을 사용합니다: ().)
6.16. Evaluation order
파이썬은 표현식을 왼쪽에서 오른쪽으로 평가합니다. 할당을 평가하는 동안 오른쪽이 왼쪽보다 먼저 평가됩니다.
다음 줄에서 식은 접미사의 산술 순서로 평가됩니다.
expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2
6.17. Operator precedence
다음 표는 가장 높은 우선 순위(가장 높은 바인딩)에서 가장 낮은 우선 순위(최소 바인딩)까지 Python의 연산자 우선 순위를 요약한 것입니다. 같은 상자에 있는 연산자는 우선 순위가 같습니다. 구문이 명시적으로 제공되지 않는 한 연산자는 이진입니다. 동일한 상자 그룹의 연산자는 왼쪽에서 오른쪽으로 그룹화됩니다(오른쪽에서 왼쪽으로 그룹화되는 지수 및 조건식 제외).
비교, 멤버십 테스트 및 ID 테스트는 모두 동일한 우선 순위를 가지며 비교 섹션에 설명된 대로 왼쪽에서 오른쪽으로 연결 기능이 있습니다.
Operator | Description |
---|---|
(expressions...) ,[expressions...] , {key: value...} , {expressions...} | Binding or parenthesized expression, list display, dictionary display, set display |
x[index] , x[index:index] , x(arguments...) , x.attribute | Subscription, slicing, call, attribute reference |
await x | Await expression |
** | Exponentiation 5 |
+x , -x , ~x | Positive, negative, bitwise NOT |
* , @ , / , // , % | Multiplication, matrix multiplication, division, floor division, remainder 6 |
+ , - | Addition and subtraction |
<< , >> | Shifts |
& | Bitwise AND |
^ | Bitwise XOR |
| | Bitwise OR |
in , not in , is , is not , < , <= , > , >= , != , == | Comparisons, including membership tests and identity tests |
not x | Boolean NOT |
and | Boolean AND |
or | Boolean OR |
if – else | Conditional expression |
lambda | Lambda expression |
:= | Assignment expression |
Source: https://docs.python.org/3/reference/expressions.html