[Python] explain the following attribute lookup

Discussão em 'Python' iniciado por Stack, Fevereiro 12, 2025.

  1. Stack

    Stack Membro Participativo

    class Test(io.BufferedIOBase):
    def __init__(self, f):
    self.f = f

    def __getattr__(self, name):
    print("getattr: searching for: ", name)
    #try:
    # v = getattr(self.f, name)
    #except Exception:
    # print(" found nothing!")
    # raise
    #print(" found: ", v)
    #return v
    #return 22
    raise AttributeError(name)

    def __getattribute__(self, name):
    print("1.getattribute@self: searching for: ", name, flush=True)
    try:
    v = super().__getattribute__(name)
    except Exception as e:
    print(" 1.exception: ", e)
    print(" 1.found nothing!", flush=True)
    pass
    else:
    print(" 1.found: ", v, flush=True)
    return v
    print("2.getattribute@self.f: searching for: ", name, flush=True)
    #f = super().__getattribute__("f")
    f = object.__getattribute__(self, "f")
    try:
    v = getattr(f, name)
    except Exception as e:
    print(" 2.exception: ", e)
    print(" 2.found nothing!", flush=True)
    raise
    else:
    print(" 2.found: ", v, flush=True)
    return v
    print("ERROR")


    f1 = open(p, "rb")
    f2 = Test(f1)
    print("\nTest 01:")
    v = f2.closed
    print("result: ", v)
    print("\nTest 02:")
    v = f2.qwer
    print("result: ", v)


    Test 01:
    1.getattribute@self: searching for: closed
    1.getattribute@self: searching for: __IOBase_closed
    1.exception: 'Test' object has no attribute '__IOBase_closed'
    1.found nothing!
    2.getattribute@self.f: searching for: __IOBase_closed
    2.exception: '_io.BufferedReader' object has no attribute '__IOBase_closed'
    2.found nothing!
    getattr: searching for: __IOBase_closed
    1.found: False
    result: False

    Test 02:
    1.getattribute@self: searching for: qwer
    1.exception: 'Test' object has no attribute 'qwer'
    1.found nothing!
    2.getattribute@self.f: searching for: qwer
    2.exception: '_io.BufferedReader' object has no attribute 'qwer'
    2.found nothing!
    getattr: searching for: qwer
    ---------------------------------------------------------------------------
    AttributeError Traceback (most recent call last)
    Cell In[532], line 49
    47 print("result: ", v)
    48 print("\nTest 02:")
    ---> 49 v = f2.qwer
    50 print("result: ", v)

    Cell In[532], line 15, in Test.__getattr__(self, name)
    6 print("getattr: searching for: ", name)
    7 #try:
    8 # v = getattr(self.f, name)
    9 #except Exception:
    (...)
    13 #return v
    14 #return 22
    ---> 15 raise AttributeError(name)

    AttributeError: qwer


    Following object_getattribute(), this is what I think happens:

    1. closed resolves to the non-data property from IOBase.
    2. The property is called before the previous __getattribute__ returns, looking up self.__closed, which is actually _IOBase__closed per name-mangling rules.

    Now the steps become strange.

    1. My __getattribute__ seems to be searching for __IOBase_closed (which doesn't exist), rather than _IOBase__closed. This I can attribute to mismatches between the Python and CPython code.
    2. My __getattribute__ fails and raises AttributeError, and then my __getattr__ fails and raises AttributeError. And yet somehow, the value of _IOBase__closed is returned. I can only explain this if Python calls another getattr* function further up the MRO.

    So now I'm stumped.

    Continue reading...

Compartilhe esta Página