>  기사  >  백엔드 개발  >  Python 마법 함수 학습 __missing__

Python 마법 함수 학습 __missing__

WBOY
WBOY원래의
2022-03-11 17:23:222301검색

이 글은 "__missing__()" 함수와 관련된 문제를 주로 소개하는 python에 대한 관련 지식을 제공합니다. 이 마법의 기능을 함께 살펴보겠습니다.

Python 마법 함수 학습 __missing__

추천 학습: python 학습 튜토리얼

1. 다소 가치 있는 __missing__()

일반 사전에서 값을 가져올 때 키가 존재하지 않을 수 있습니다:

dd = {'name':'PythonCat'}
dd.get('age')        # 结果:None
dd.get('age', 18)    # 结果:18
dd['age']            # 报错 KeyError
dd.__getitem__('age')  # 等同于 dd['age']

Python 마법 함수 학습 __missing__

가져오기 () 메서드에는 반환 값이 있고, 키가 없을 때 두 번째 매개 변수를 반환 내용으로 전달할 수 있으므로 허용됩니다. 그러나 다른 두 가지 쓰기 방법에서는 오류가 보고됩니다.

후자의 두 가지 작성 방법의 문제를 해결하기 위해 __missing__() 매직 방법을 사용할 수 있습니다.

이제 다음과 같은 요청이 있다고 가정해 보겠습니다. 사전에서 특정 키에 해당하는 값을 가져오고, 값이 있으면 값을 반환하고, 값이 없으면 키를 삽입하고, 기본값을 지정합니다(예: 빈 목록으로).

네이티브 dict를 사용하면 구현하기가 쉽지 않습니다. 그러나 Python은 사용하기 매우 쉬운 확장 클래스 collections.defaultdict를 제공합니다. collections.defaultdict

Python 마법 함수 학습 __missing__

如图所示,当取不存在的 key 时,没有再报 KeyError,而是默认存入到字典中。

为什么 defaultdict 可以做到这一点呢?

原因是 defaultdict 在继承了内置类型 dict 之后,还定义了一个 __missing__() 方法,当 __getitem__取不存在的值时,它就会调用入参中传入的工厂函数(上例是调用 list(),创建空列表)。

作为最典型的示例,defaultdict 在文档注释中写到:

Python 마법 함수 학습 __missing__

简而言之,__missing__()的主要作用就是由__getitem__在缺失 key 时调用,从而避免出现 KeyError。

另外一个典型的使用例子是collections.Counter,它也是 dict 的子类,在取未被统计的 key 时,返回计数 0:

Python 마법 함수 학습 __missing__

2、神出鬼没的__missing__()

由上可知,__missing__()在__getitem__()取不到值时会被调用,但是,我不经意间还发现了一个细节:__getitem__()在取不到值时,并不一定会调用__missing__()。

这是因为它并非内置类型的必要属性,并没有在字典基类中被预先定义。

如果你直接从 dict 类型中取该属性值,会报属性不存在:AttributeError: type object 'object' has no attribute '__missing__'

Python 마법 함수 학습 __missing__

그림과 같이, 존재하지 않는 키를 가져오는 중 더 이상 KeyError를 보고하지 않지만 기본적으로 사전에 저장합니다.

Python 마법 함수 학습 __missing__defaultdict가 왜 이런 일을 할 수 있나요?

그 이유는 defaultdict가 내장 유형 dict를 상속한 후 __missing__() 메서드도 정의하기 때문입니다. __getitem__이 존재하지 않는 값을 취하면 입력 매개 변수에 전달된 팩토리 함수를 호출합니다(위의 예는 Call입니다). list(), 빈 목록 생성).

가장 일반적인 예로서 defaultdict는 문서 주석에 다음과 같이 씁니다:

Python 마법 함수 학습 __missing__

간단히 말하면, Python 마법 함수 학습 __missing____missing__()의 주요 함수는 키가 누락되었을 때 __getitem__에 의해 호출되어 KeyError를 방지하는 것입니다.

또 다른 일반적인 사용 예는 dict의 하위 클래스이기도 한 collections.Counter입니다. 계산되지 않은 키를 사용하면 개수가 0으로 반환됩니다.

Python 마법 함수 학습 __missing__

2.

가능한 한 위에서 볼 수 있듯이 __getitem__()이 값을 얻을 수 없을 때 __missing__()이 호출됩니다. 그러나 우연히 세부 사항을 발견했습니다:

__getitem__()은 값을 얻을 수 없을 때 반드시 __missing__(을 호출하지는 않습니다.)

내장형의 필수 속성도 아니고 딕셔너리 기반 클래스에 미리 정의되어 있지도 않기 때문입니다.

Python 마법 함수 학습 __missing__dict 유형에서 직접 속성 값을 가져오면 속성이 존재하지 않는다고 보고됩니다: AttributeError: type object 'object' has no attribute '__missing__'.

🎜dir()을 사용하여 속성이 존재하지 않는지 확인하고 찾습니다. 🎜🎜🎜🎜🎜객체인 dict의 상위 클래스에서 확인하면 동일한 결과를 찾을 수 있습니다. 🎜🎜무슨 일이 일어나고 있나요? dict와 object 모두에 __missing__ 속성이 없는 이유는 무엇입니까? 🎜🎜그러나 최신 공식 문서를 확인하면 객체에 다음 속성이 분명히 포함되어 있습니다: 🎜🎜🎜🎜🎜출처: https://docs.python.org/3/reference/datamodel.html?highlight=__missing__#object.__missing__🎜 🎜 즉, 이론적으로 __missing__은 객체 클래스에 미리 정의되어 있고, 문서에서도 이를 입증하지만 실제로는 정의되어 있지 않습니다! 문서와 실제 사이에 차이가 있습니다! 🎜🎜이런 식으로 dict의 하위 클래스(예: defaultdict 및 Counter)가 __missing__을 정의하면 이 매직 메서드는 실제로 해당 하위 클래스에만 속합니다. 즉, 🎜하위 클래스에서 탄생한 매직 메서드입니다! 🎜🎜🎜이에 따르면 미성숙한 추측이 있습니다. __getitem__()은 현재 개체가 dict의 하위 클래스인지, __missing__()이 있는지 확인한 다음 이를 호출합니다(부모 클래스에도 이 메서드가 있는 경우 먼저 판단하지 않고 직접 호출합니다.) 🎜🎜저는 커뮤니케이션 그룹에서 이 추측을 언급했고 일부 학생들은 CPython 소스 코드에서 그 검증을 빨리 발견했습니다: 🎜🎜🎜🎜

그리고 이것은 흥미롭습니다. 내장 유형의 하위 클래스에만 존재하는 마법 메서드, 전체 Python 세계를 살펴보면 아마도 두 번째 예를 찾기가 어려울 것입니다.

갑자기 연상이 생겼습니다. 이 파악하기 어려운 __missing__()은 "살아있는 사람을 변화시키는" 데 능숙한 마술사와 같습니다. 먼저 관객이 외부 유리(예: 공식 문서)를 통해 그를 볼 수 있도록 하세요. 열면 그는 내부에 있지 않으며(즉, 내장 유형) props가 변경되면 다시 그대로 나타납니다(즉, dict의 하위 클래스).

3. 마법에 걸린 __missing__()

__missing__()의 마법은 "마법" 자체 외에도 강력한 "마법"이 필요합니다.

지난 기사에서 네이티브 매직 메서드는 C 언어 인터페이스에서 동일한 핵심 논리를 가질 수 있지만 Python 언어 인터페이스에는 호출 관계가 없다는 것을 발견했습니다.

Python 마법 함수 학습 __missing__

Magic 이러한 종류의 메소드 "비접촉" 성능은 일반적인 코드 재사용 원칙을 위반하며 내장 유형의 하위 클래스가 이상한 동작을 하는 이유이기도 합니다.

공식 Python에서는 매직 메서드를 재사용하는 것보다 새로운 UserString, UserList 및 UserDict 하위 클래스를 제공하는 것이 합리적일 수 있습니다. 유일한 합리적인 설명은 매직 메서드를 서로 호출하는 데 드는 비용이 너무 높다는 것입니다.

그러나 특별한 경우인 __missing__()의 경우 Python은 타협하고 이 대가를 지불해야 합니다!

__missing__()은 마법 메서드의 "2등급 시민"입니다. 독립적인 호출 항목이 없으며 __getitem__()에 의해 수동적으로만 호출될 수 있습니다. 즉, __missing__()은 __getitem__()에 따라 다릅니다.

__init__(), __enter__(), __len__(), __eq__() 등과 같은 "일류 시민"과는 달리 객체 수명 주기 또는 실행의 특정 노드에서 트리거됩니다. 프로세스는 내장 함수나 연산자에 의해 트리거되며 상대적으로 독립적인 이벤트이며 종속성이 없습니다.

__missing__()은 메서드 호출을 수행하기 위해 __getitem__()에 의존하고 __getitem__()도 완전한 기능을 수행하기 위해 __missing__()에 의존합니다.

이를 달성하기 위해 __getitem__()은 인터프리터 코드에서 백도어를 열고 C 언어 인터페이스에서 Python 인터페이스로 돌아와 "__missing__"이라는 특정 메서드를 호출합니다.

Python 마법 함수 학습 __missing__

그리고 이것이 진짜 "마술"입니다. 지금까지는 __missing__()만이 그러한 치료를 즐기는 유일한 마술 방법인 것 같습니다!

4. 요약

Python의 사전은 값을 얻기 위한 두 가지 내장 메서드, 즉 __getitem__()과 get()을 제공합니다. 값이 존재하지 않으면 처리 전략이 다릅니다. 전자는 오류를 보고합니다. >KeyError, None을 반환합니다. KeyError,而后者会返回 None。

为什么 Python 要提供两个不同的方法呢?或者应该问,为什么 Python 要令这两个方法做出不一样的处理呢?

这可能有一个很复杂(也可能是很简单)的解释,本文暂不深究了。

不过有一点是可以确定的:即原生 dict 类型简单粗暴地抛KeyError

왜 Python은 두 가지 다른 방법을 제공하나요? 아니면 왜 Python이 이 두 메서드를 다르게 처리하는지 물어봐야 할까요?

설명이 매우 복잡할 수도 있고 매우 간단할 수도 있으므로 이 글에서는 다루지 않겠습니다. 하지만 한 가지는 확실합니다. 기본 dict 유형은 간단하고 거칠게 KeyError를 발생시킵니다.

사전 유형에 더 강력한 성능을 제공하기 위해(또는 __getitem__()이 get()처럼 작동하도록) Python에서는 사전의 하위 클래스에서 __getitem__()이 검색하고 호출할 수 있도록 __missing__()을 정의할 수 있습니다.

이 기사에서는 __missing__()의 구현 원칙을 정리하여 눈에 띄지 않는 존재가 아니라는 사실을 드러냅니다. 매직 메소드 간의 장벽을 허물고 다른 매직 메소드에 의해 호출되는 것을 지원하는 유일한 특수 사례입니다!

🎜매직 메서드의 독립성을 유지하기 위해 Python은 UserString, UserList 및 UserDict와 같은 파생 클래스를 도입하는 데 많은 노력을 기울였지만 __missing__()의 경우 타협을 선택했습니다. 🎜🎜추천 학습: 🎜python 튜토리얼🎜🎜

위 내용은 Python 마법 함수 학습 __missing__의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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