programing

__eq_는 Python에서 어떻게 처리되고 어떤 순서로 처리됩니까?

topblog 2023. 7. 17. 20:30
반응형

__eq_는 Python에서 어떻게 처리되고 어떤 순서로 처리됩니까?

파이썬은 비교 연산자의 왼쪽/오른쪽 버전을 제공하지 않기 때문에 어떤 함수를 호출할지 어떻게 결정합니까?

class A(object):
    def __eq__(self, other):
        print "A __eq__ called"
        return self.value == other
class B(object):
    def __eq__(self, other):
        print "B __eq__ called"
        return self.value == other

>>> a = A()
>>> a.value = 3
>>> b = B()
>>> b.value = 4
>>> a == b
"A __eq__ called"
"B __eq__ called"
False

이것은 둘 다를 부르는 것처럼 보입니다.__eq__기능들.

저는 공식 결정 트리를 찾고 있습니다.

a == b 식호를 호출합니다.A.__eq__그것이 존재하기 때문에코드는 다음을 포함합니다.self.value == otherint에, 은 int를 호출하려고 .B.__eq__자신을 int와 비교하는 방법을 알고 있는지 알아보기 위해.

비교 중인 값을 표시하도록 코드를 수정하는 경우:

class A(object):
    def __eq__(self, other):
        print("A __eq__ called: %r == %r ?" % (self, other))
        return self.value == other
class B(object):
    def __eq__(self, other):
        print("B __eq__ called: %r == %r ?" % (self, other))
        return self.value == other

a = A()
a.value = 3
b = B()
b.value = 4
a == b

다음과 같이 출력됩니다.

A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ?
B __eq__ called: <__main__.B object at 0x013BA090> == 3 ?

가 Python2를 볼 때.x에서 다음을 확인할 때a == b다음과 같은 시도를 합니다.

  • 한다면type(b)이고, 새운스수업고이의타일로,,,type(b)의 하위 클래스입니다.type(a),그리고.type(b)오버라이드했습니다.__eq__그렇다면 결과는b.__eq__(a).
  • 한다면type(a)오버라이드했습니다.__eq__ (계속)type(a).__eq__그렇지 않은object.__eq__는 , , 입니다.a.__eq__(b).
  • 한다면type(b)오버라이드했습니다.__eq__그렇다면 결과는b.__eq__(a).
  • 되지 않을 , 은 위의내모해않는경우은지, Python반복합다니프를로스세찾는음을다용이를 합니다.__cmp__그것이 존재한다면, 이 반환된다면, 그 객체들은 같습니다.zero.
  • 은 Python을 최종예고객라고 .object.__eq__(a, b),어느 것이True만약에a그리고.b동일한 개체입니다.

특수한 방법 중 하나라도 반환되는 경우NotImplementedPython은 메서드가 존재하지 않는 것처럼 동작합니다.

를 주의 깊게 : 것도 그렇지 않다면.a도 아니다b==,그리고나서a == b는 와동합다니와 .a is b.


출처: https://eev.ee/blog/2012/03/24/python-faq-equality/

이 알고리즘에 대한 Python 3 변경/업데이트

어떻게 있다.__eq__Python에서 처리되며 어떤 순서로 처리됩니까?

a == b

그런 것은 아닙니다.a == b출호를 합니다.a.__eq__(b)또는type(a).__eq__(a, b).

분명히 평가 순서는 다음과 같습니다.

  1. 한다면b은 의유동은의엄하클아다래니입위스격의 엄격한 클래스유형이 a의 유형과 유형이 있습니다.__eq__합니다.
  2. 그렇지 않으면, 만약a가지다__eq__ 그것을 참조하십시오.
  3. 아니면, 우리가 B에게 전화하지 않았는지 보세요.__eq__, , 리고그그가있고, 비실그전돌다려니줍.
  4. 동일성에 합니다. 동일성에 대한 비교는 으로그에, 정막대비하, 체비를하라같, 를라교은교한과 같은 입니다.is.

메소드가 반환되는 경우 비교가 구현되지 않는지 여부를 알고 있습니다.NotImplemented.

에는 (파이썬 2)가.__cmp__찾았지만 Python 3에서 더 이상 사용되지 않고 제거된 메서드입니다.)

B를 하위 클래스 A로 지정하여 첫 번째 검사의 동작을 직접 테스트해 보겠습니다. A는 이 카운트에서 허용된 답변이 잘못되었음을 나타냅니다.

class A:
    value = 3
    def __eq__(self, other):
        print('A __eq__ called')
        return self.value == other.value

class B(A):
    value = 4
    def __eq__(self, other):
        print('B __eq__ called')
        return self.value == other.value

a, b = A(), B()
a == b

은 오직 만 합니다.B __eq__ called False.

참고로 다음과 같은 질문에서 작은 오류도 수정합니다.self.value 됩니다.otherother.value에서, 는 두 의 물체이비교우리, 물는두개얻다습니체를의서에▁(다이)를 얻습니다.self그리고.other를 하지 않기 유형의 입니다. (은 다른 수 ), 우리는 그것들이 한지 알아야 .), 여서는그유검형동수일유며로으반일않이형적동있합때문다수음알니일야여한아다한기를부지를러나유에이형기사행하지를▁),그▁usually동다합일▁of-▁since),니▁(▁we야),but▁are▁if▁are한여▁the알▁here여▁and지아▁type▁we▁they▁equal▁doing▁samechecking▁no▁type▁types(▁need부를기▁they),음있▁to그들이 동등한지 아닌지에 대한 우리의 측정은 다음을 확인하는 것입니다.value속성. 두 개체 모두에서 수행해야 합니다.

이 완전한 알고리즘을 어떻게 알 수 있을까요?

여기에 있는 다른 답변들은 불완전하고 구식인 것 같습니다. 그래서 저는 정보를 업데이트하고 여러분이 어떻게 이것을 직접 찾을 수 있는지 보여드리겠습니다.

이것은 C 레벨에서 처리됩니다.

우리는 여기서 두 개의 다른 코드 비트 - 기본값을 살펴볼 필요가 있습니다.__eq__에급▁의 객체에 대해.object그리고 코드를 찾아 전화를 거는 것입니다.__eq__입니다.__eq__또는 사용자 지정된 것.

__eq__

중 ㅠㅠ__eq__관련 Capi 문서에 있는 것은 우리에게 보여줍니다.__eq__에 의해 처리됨 - 의"object"의 형식 정의는 다음에서 정의됩니다.object_richcompare위해서case Py_EQ:.

    case Py_EQ:
        /* Return NotImplemented instead of False, so if two
           objects are compared, both get a chance at the
           comparison.  See issue #1393. */
        res = (self == other) ? Py_True : Py_NotImplemented;
        Py_INCREF(res);
        break;

그래서 여기, 만약에.self == other우리는 돌아옵니다.True그렇지 않으면 반환합니다.NotImplemented물건.자체적으로 구현하지 않는 모든 하위 클래스의 기본 동작입니다.__eq__방법.

어떻게.__eq__ 불립니다.

그런 다음 C API 문서인 PyObject_RichCompare 함수를 찾습니다. 이 함수는 다음을 호출합니다.do_richcompare.

그러면 우리는 그것을 봅니다.tp_richcompare, 다을위를 위해 생성됨"object"C 정의는 다음과 같이 호출됩니다.do_richcompare좀 더 자세히 살펴보도록 하겠습니다.

이 기능의 첫 번째 점검은 비교 중인 물체의 상태에 대한 것입니다.

  • 동일한 유형은 아니지만,
  • 두 번째 유형은 첫 번째 유형의 하위 클래스입니다.
  • 두 번째 유형은 다음과 같습니다.__eq__ 변수,

그런 다음 인수가 스왑된 다른 메소드를 호출하여 구현된 경우 값을 반환합니다.만약 그 방법이 실행되지 않는다면, 우리는 계속...

    if (!Py_IS_TYPE(v, Py_TYPE(w)) &&
        PyType_IsSubtype(Py_TYPE(w), Py_TYPE(v)) &&
        (f = Py_TYPE(w)->tp_richcompare) != NULL) {
        checked_reverse_op = 1;
        res = (*f)(w, v, _Py_SwappedOp[op]);
        if (res != Py_NotImplemented)
            return res;
        Py_DECREF(res);

다음에는 우리가 찾을 수 있는지 살펴봅니다.__eq__메서드를 첫 번째 유형에서 호출합니다.결과가 구현되지 않은 경우, 즉 구현된 경우에는 반환합니다.

    if ((f = Py_TYPE(v)->tp_richcompare) != NULL) {
        res = (*f)(v, w, op);
        if (res != Py_NotImplemented)
            return res;
        Py_DECREF(res);

그렇지 않으면 다른 유형의 방법을 시도하지 않고 사용해 보고 비교가 구현되면 반환합니다.

    if (!checked_reverse_op && (f = Py_TYPE(w)->tp_richcompare) != NULL) {
        res = (*f)(w, v, _Py_SwappedOp[op]);
        if (res != Py_NotImplemented)
            return res;
        Py_DECREF(res);
    }

마지막으로, 우리는 어느 한 사람의 유형에 대해서도 구현되지 않은 경우에 대비합니다.

합니다. - 은 개의은체즉 ID, 동위있개여동부확일다지인합니를체인치일는한과 한 입니다. 이는 다음과 같은 검사입니다.self is other:

    /* If neither object implements it, provide a sensible default
       for == and !=, but raise an exception for ordering. */
    switch (op) {
    case Py_EQ:
        res = (v == w) ? Py_True : Py_False;
        break;

결론

비교에서, 우리는 비교의 하위 클래스 구현을 먼저 존중합니다.

그런 다음 첫 번째 개체의 구현과 비교하고, 호출되지 않은 두 번째 개체의 구현과 비교합니다.

마지막으로 동일성에 대한 비교를 위해 동일성에 대한 테스트를 사용합니다.

언급URL : https://stackoverflow.com/questions/3588776/how-is-eq-handled-in-python-and-in-what-order

반응형