목차
머리말
Introduction
归纳这些方法
我发现几乎没有人使用**=
이러한 메소드를 일반화하세요
백엔드 개발 파이썬 튜토리얼 강화된 연산 할당 '-=' 연산에 대한 자세한 설명

강화된 연산 할당 '-=' 연산에 대한 자세한 설명

Sep 11, 2020 pm 05:11 PM
python 과제

강화된 연산 할당 '-=' 연산에 대한 자세한 설명

관련 학습 권장 사항: python 튜토리얼

머리말

이 문서는 Python 구문 설탕에 대한 일련의 문서 중 하나입니다. 최신 소스 코드는 desugar 프로젝트(github.com/brettcannon…

Introduction

Python에는 향상된 산술 할당(증강 산술 할당)이라는 기능이 있습니다. 아마 여러분은 이에 익숙하지 않을 수도 있습니다. 호출됨 수학 연산을 수행하면서 실제로 할당을 수행합니다. 예를 들어 a -= b는 뺄셈의 향상된 산술 할당입니다. 增强算术赋值(augmented arithmetic assignment)的东西。可能你不熟悉这个叫法,其实就是在做数学运算的同时进行赋值,例如 a -= b 就是减法的增强算术赋值。

增强赋值是在 Python 2.0 版本中 加入进来的。(译注:在 PEP-203 中引入)

剖析-=

因为 Python 不允许覆盖式赋值,所以相比其它有特殊/魔术方法的操作,它实现增强赋值的方式可能跟你想象的不完全一样。

首先,要知道a -= b在语义上与 a = a-b 相同。但也要意识到,如果你预先知道要将一个对象赋给一个变量名,相比a - b 的盲操作,就可能会更高效。

例如,最起码的好处是可以避免创建一个新对象:如果可以就地修改一个对象,那么返回 self,就比重新构造一个新对象要高效。

因此,Python 提供了一个__isub__() 方法。如果它被定义在赋值操作的左侧(通常称为 lvalue),则会调用右侧的值(通常称为 rvalue )。所以对于a -= b ,就会尝试去调用 a.__isub__(b)。

如果调用的结果是 NotImplemented,或者根本不存在结果,那么 Python 会退回到常规的二元算术运算:a - b。(译注:作者关于二元运算的文章,译文在此)

最终无论用了哪种方法,返回值都会被赋值给 a。

下面是简单的伪代码,a -= b 被分解成:

# 实现 a -= b 的伪代码if hasattr(a, "__isub__"):
    _value = a.__isub__(b)    if _value is not NotImplemented:
        a = _value    else:
        a = a - b    del _value else:
     a = a - b复制代码
로그인 후 복사

归纳这些方法

由于我们已经实现了二元算术运算,因此归纳增强算术运算并不太复杂。

通过传入二元算术运算函数,并做一些自省(以及处理可能发生的 TypeError),它可以被漂亮地归纳成:

def _create_binary_inplace_op(binary_op: _BinaryOp) -> Callable[[Any, Any], Any]:

    binary_operation_name = binary_op.__name__[2:-2]
    method_name = f"__i{binary_operation_name}__"
    operator = f"{binary_op._operator}="

    def binary_inplace_op(lvalue: Any, rvalue: Any, /) -> Any:
        lvalue_type = type(lvalue)        try:
            method = debuiltins._mro_getattr(lvalue_type, method_name)        except AttributeError:            pass
        else:
            value = method(lvalue, rvalue)            if value is not NotImplemented:                return value        try:            return binary_op(lvalue, rvalue)        except TypeError as exc:            # If the TypeError is due to the binary arithmetic operator, suppress
            # it so we can raise the appropriate one for the agumented assignment.
            if exc._binary_op != binary_op._operator:                raise
        raise TypeError(            f"unsupported operand type(s) for {operator}: {lvalue_type!r} and {type(rvalue)!r}"
        )

    binary_inplace_op.__name__ = binary_inplace_op.__qualname__ = method_name
    binary_inplace_op.__doc__ = (        f"""Implement the augmented arithmetic assignment `a {operator} b`."""
    )    return binary_inplace_op复制代码
로그인 후 복사

这使得定义的 -= 支持 _create_binary_inplace_op(__ sub__),且可以推断出其它内容:函数名、调用什么 __i*__ 函数,以及当二元算术运算出问题时,该调用哪个可调用对象。

我发现几乎没有人使用**=

在写本文的代码时,我碰上了 **= 的一个奇怪的测试错误。在所有确保 __pow__ 会被适当地调用的测试中,有个测试用例对于 Python 标准库中的operator 模块却是失败。

我的代码通常没问题,如果代码与 CPython 的代码之间存在差异,通常会意味着是我哪里出错了。

但是,无论我多么仔细地排查代码,我都无法定位出为什么我的测试会通过,而标准库则失败。

我决定深入地了解 CPython 内部发生了什么。从反汇编字节码开始:

>>> def test(): a **= b... >>> import dis>>> dis.dis(test)  1           0 LOAD_FAST                0 (a)              2 LOAD_GLOBAL              0 (b)              4 INPLACE_POWER              6 STORE_FAST               0 (a)              8 LOAD_CONST               0 (None)             10 RETURN_VALUE复制代码
로그인 후 복사

通过它,我找到了在 eval 循环中的INPLACE_POWER

        case TARGET(INPLACE_POWER): {
            PyObject *exp = POP();
            PyObject *base = TOP();
            PyObject *res = PyNumber_InPlacePower(base, exp, Py_None);
            Py_DECREF(base);
            Py_DECREF(exp);
            SET_TOP(res);            if (res == NULL)                goto error;
            DISPATCH();
        }复制代码
로그인 후 복사

出处:github.com/python/cpyt…

然后找到PyNumber_InPlacePower()

Python 2.0에서 향상된 할당이 추가되었습니다. (번역: PEP-203에서 도입됨)

분석-=

파이썬은 덮어쓰기 할당을 허용하지 않기 때문에 특수/마법 메서드를 사용하는 다른 작업에 비해 향상된 할당을 구현합니다.

먼저, a -= b는 의미론적으로 a = a-b와 동일하다는 점을 알아두세요. 하지만 객체를 a에 할당하려는 것을 미리 알고 있다면 변수 이름은 a - b의 맹목적인 작업보다 더 효율적일 수 있습니다. 예를 들어, 최소한의 이점은 새 개체 생성을 피할 수 있다는 것입니다. 개체를 제자리에서 수정할 수 있는 경우 self를 반환하면 새 객체를 재구성하는 것보다 더 효율적입니다. 따라서 할당 작업의 왼쪽에 정의된 경우(일반적으로 lvalue라고 함) Python은 __isub__() 메서드를 제공하고 오른쪽의 값(일반적으로 rvalue라고 함)은 다음과 같습니다. 따라서 a -= b의 경우 a.__isub__(b) 호출을 시도합니다.

호출 결과가 NotImplemented이거나 결과가 전혀 없으면 Python은 실패합니다. 일반 이진 산술 연산으로 돌아가기: a - b (주석: 이진 연산에 대한 저자의 기사, 번역은 여기에 있음)

결국 어떤 방법을 사용하든 반환 값은 다음과 같습니다.

다음은 간단한 의사 코드입니다. a -= b는 다음과 같이 분해됩니다.

PyObject *PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z){    if (v->ob_type->tp_as_number &&
        v->ob_type->tp_as_number->nb_inplace_power != NULL) {        return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");
    }    else {        return ternary_op(v, w, z, NB_SLOT(nb_power), "**=");
    }
}复制代码
로그인 후 복사

이러한 메소드를 일반화하세요

이미 이진 산술이 구현되어 있으므로 향상된 산술을 일반화하는 것은 그리 복잡하지 않습니다.

이진 산술 연산 함수를 전달하고 몇 가지 자체 검사(발생할 수 있는 TypeError 처리 포함)를 수행하면 다음과 같이 깔끔하게 요약될 수 있습니다. rrreee이것은 정의된 _create_binary_inplace_op(__ sub__)를 지원하고 함수 이름, 호출되는 __i*__ 함수, 이진 산술 연산 시 문제가 발생할 때 호출할 수 있는 항목 등을 추론할 수 있습니다.

**=를 사용하는 사람이 거의 없다는 사실을 발견했습니다

이 기사의 코드를 작성하는 동안 **=에 대한 이상한 테스트에 직면했습니다. 실수. __pow__가 적절하게 호출되는지 확인하는 모든 테스트 중에서 Python 표준 라이브러리의 operator 모듈에 대해 실패하는 테스트가 있습니다. 🎜🎜내 코드는 일반적으로 문제가 없으며, 코드와 CPython의 코드 사이에 차이가 있으면 일반적으로 내가 뭔가 잘못하고 있다는 의미입니다. 🎜🎜그러나 코드 문제를 아무리 주의 깊게 해결해도 테스트는 통과하는데 표준 라이브러리는 실패하는 이유를 정확히 알 수 없습니다. 🎜🎜저는 CPython 내부에서 무슨 일이 일어나고 있는지 자세히 살펴보기로 했습니다. 디스어셈블리 바이트코드에서 시작: 🎜rrreee🎜이를 통해 평가 루프에서 INPLACE_POWER를 찾았습니다: 🎜rrreee🎜출처: github.com/python/cpyt…🎜🎜그런 다음 PyNumber_InPlacePower( ): 🎜rrreee🎜출처: github.com/python/cpyt…🎜🎜안심 ~ 코드는 __ipow__가 정의되면 호출되지만 __ipow__가 없는 경우에만 __pow__가 호출된다는 것을 보여줍니다. 🎜🎜그러나 올바른 접근 방식은 다음과 같습니다. 🎜 __ipow__를 호출할 때 문제가 발생하여 NotImplemented를 반환하거나 전혀 반환이 없는 경우 __pow__ 및 __rpow__를 호출해야 합니다. 🎜🎜🎜즉, 위 코드는 __ipow__가 있을 때 실수로 a**b의 대체 의미를 건너뛰는 것입니다! 🎜🎜사실 이 문제는 부분적으로 발견되었으며 약 11개월 전에 버그가 접수되었습니다. 문제를 해결하고 python-dev에 문서화했습니다. 🎜🎜현재로서는 Python 3.10에서 이 문제가 수정될 것으로 보입니다. 또한 3.8 및 3.9 문서에 **= 버그가 있다는 알림을 추가해야 합니다(이 문제는 오래 전에 있었을 수도 있지만 이전 Python 버전에는 보안 전용 유지 관리 모드가 있으므로 설명서는 변경되지 않습니다. 🎜🎜수정된 코드는 의미론적 변경이므로 이식되지 않을 가능성이 높으며 누군가 실수로 문제가 있는 의미론에 의존했는지 알기 어렵습니다. 하지만 이 문제가 발견되기까지 너무 오랜 시간이 걸렸습니다. 이는 **=가 널리 사용되지 않았음을 의미합니다. 그렇지 않으면 문제가 오래 전에 발견되었을 것입니다. 🎜🎜🎜프로그래밍 학습에 대해 더 자세히 알고 싶다면 🎜php training🎜 칼럼을 주목해주세요! 🎜🎜🎜

위 내용은 강화된 연산 할당 '-=' 연산에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

PHP 및 Python : 코드 예제 및 비교 PHP 및 Python : 코드 예제 및 비교 Apr 15, 2025 am 12:07 AM

PHP와 Python은 고유 한 장점과 단점이 있으며 선택은 프로젝트 요구와 개인 선호도에 달려 있습니다. 1.PHP는 대규모 웹 애플리케이션의 빠른 개발 및 유지 보수에 적합합니다. 2. Python은 데이터 과학 및 기계 학습 분야를 지배합니다.

Centos에서 Pytorch에 대한 GPU 지원은 어떻습니까? Centos에서 Pytorch에 대한 GPU 지원은 어떻습니까? Apr 14, 2025 pm 06:48 PM

CentOS 시스템에서 Pytorch GPU 가속도를 활성화하려면 Cuda, Cudnn 및 GPU 버전의 Pytorch를 설치해야합니다. 다음 단계는 프로세스를 안내합니다. CUDA 및 CUDNN 설치 CUDA 버전 호환성 결정 : NVIDIA-SMI 명령을 사용하여 NVIDIA 그래픽 카드에서 지원하는 CUDA 버전을보십시오. 예를 들어, MX450 그래픽 카드는 CUDA11.1 이상을 지원할 수 있습니다. Cudatoolkit 다운로드 및 설치 : NVIDIACUDATOOLKIT의 공식 웹 사이트를 방문하여 그래픽 카드에서 지원하는 가장 높은 CUDA 버전에 따라 해당 버전을 다운로드하여 설치하십시오. CUDNN 라이브러리 설치 :

Docker 원리에 대한 자세한 설명 Docker 원리에 대한 자세한 설명 Apr 14, 2025 pm 11:57 PM

Docker는 Linux 커널 기능을 사용하여 효율적이고 고립 된 응용 프로그램 실행 환경을 제공합니다. 작동 원리는 다음과 같습니다. 1. 거울은 읽기 전용 템플릿으로 사용되며, 여기에는 응용 프로그램을 실행하는 데 필요한 모든 것을 포함합니다. 2. Union 파일 시스템 (Unionfs)은 여러 파일 시스템을 스택하고 차이점 만 저장하고 공간을 절약하고 속도를 높입니다. 3. 데몬은 거울과 컨테이너를 관리하고 클라이언트는 상호 작용을 위해 사용합니다. 4. 네임 스페이스 및 CGroup은 컨테이너 격리 및 자원 제한을 구현합니다. 5. 다중 네트워크 모드는 컨테이너 상호 연결을 지원합니다. 이러한 핵심 개념을 이해 함으로써만 Docker를 더 잘 활용할 수 있습니다.

Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스 Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스 Apr 15, 2025 am 12:16 AM

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

미니 오펜 센토 호환성 미니 오펜 센토 호환성 Apr 14, 2025 pm 05:45 PM

Minio Object Storage : Centos System Minio 하의 고성능 배포는 Go Language를 기반으로 개발 한 고성능 분산 객체 저장 시스템입니다. Amazons3과 호환됩니다. Java, Python, JavaScript 및 Go를 포함한 다양한 클라이언트 언어를 지원합니다. 이 기사는 CentOS 시스템에 대한 Minio의 설치 및 호환성을 간단히 소개합니다. CentOS 버전 호환성 Minio는 다음을 포함하되 이에 국한되지 않는 여러 CentOS 버전에서 확인되었습니다. CentOS7.9 : 클러스터 구성, 환경 준비, 구성 파일 설정, 디스크 파티셔닝 및 미니를 다루는 완전한 설치 안내서를 제공합니다.

Centos에서 Pytorch의 분산 교육을 운영하는 방법 Centos에서 Pytorch의 분산 교육을 운영하는 방법 Apr 14, 2025 pm 06:36 PM

CentOS 시스템에 대한 Pytorch 분산 교육에는 다음 단계가 필요합니다. Pytorch 설치 : 전제는 Python과 PIP가 CentOS 시스템에 설치된다는 것입니다. CUDA 버전에 따라 Pytorch 공식 웹 사이트에서 적절한 설치 명령을 받으십시오. CPU 전용 교육의 경우 다음 명령을 사용할 수 있습니다. PipinStalltorchtorchvisiontorchaudio GPU 지원이 필요한 경우 CUDA 및 CUDNN의 해당 버전이 설치되어 있는지 확인하고 해당 PyTorch 버전을 설치하려면 설치하십시오. 분산 환경 구성 : 분산 교육에는 일반적으로 여러 기계 또는 단일 기계 다중 GPU가 필요합니다. 장소

Centos에서 Pytorch 버전을 선택하는 방법 Centos에서 Pytorch 버전을 선택하는 방법 Apr 14, 2025 pm 06:51 PM

CentOS 시스템에 Pytorch를 설치할 때는 적절한 버전을 신중하게 선택하고 다음 주요 요소를 고려해야합니다. 1. 시스템 환경 호환성 : 운영 체제 : CentOS7 이상을 사용하는 것이 좋습니다. Cuda 및 Cudnn : Pytorch 버전 및 Cuda 버전은 밀접하게 관련되어 있습니다. 예를 들어, pytorch1.9.0은 cuda11.1을 필요로하고 Pytorch2.0.1은 cuda11.3을 필요로합니다. CUDNN 버전도 CUDA 버전과 일치해야합니다. Pytorch 버전을 선택하기 전에 호환 CUDA 및 CUDNN 버전이 설치되었는지 확인하십시오. 파이썬 버전 : Pytorch 공식 지점

Centos에 nginx를 설치하는 방법 Centos에 nginx를 설치하는 방법 Apr 14, 2025 pm 08:06 PM

Centos Nginx를 설치하려면 다음 단계를 수행해야합니다. 개발 도구, PCRE-DEVEL 및 OPENSSL-DEVEL과 같은 종속성 설치. nginx 소스 코드 패키지를 다운로드하고 압축을 풀고 컴파일하고 설치하고 설치 경로를/usr/local/nginx로 지정하십시오. nginx 사용자 및 사용자 그룹을 만들고 권한을 설정하십시오. 구성 파일 nginx.conf를 수정하고 청취 포트 및 도메인 이름/IP 주소를 구성하십시오. Nginx 서비스를 시작하십시오. 종속성 문제, 포트 충돌 및 구성 파일 오류와 같은 일반적인 오류는주의를 기울여야합니다. 캐시를 켜고 작업자 프로세스 수 조정과 같은 특정 상황에 따라 성능 최적화를 조정해야합니다.

See all articles