Cuando digo “proceso de búsqueda de atributo de Python” quiero decir: ¿qué hace python cuando escribes x.foo?
Buscando en la web no encontré demasiados documentos sobre esto, uno de los mejores artículos que encontré resumió el proceso a los siguientes pasos (puede ver el artículo completo aquí )
Al principio, esto puede parecer correcto, pero el proceso de búsqueda de atributos es un poco más complicado, por ejemplo para x.foo, no se comporta igual si x es una clase o una instancia.
He encontrado algunas muestras que no se pueden explicar de esta manera. Considere el siguiente código de Python:
class Meta(type): def __getattribute__(self, name): print("Metaclass getattribute invoked:", self) return type.__getattribute__(self, name) def __getattr__(self, item): print('Metaclass getattr invoked: ', item) return None class C(object, metaclass=Meta): def __getattribute__(self, name): print("Class getattribute invoked:", args) return object.__getattribute__(self, name) c=C()
Ahora revisa las siguientes líneas con la salida correspondiente:
>> C.__new__ Metaclass getattribute invoked: >> C.__getattribute__ Metaclass getattribute invoked: >> C.xyz Metaclass getattribute invoked: Metaclass getattr invoked: xyz None >> c.__new__ Class getattribute invoked: (, '__new__') >> c.__getattribute__ Class getattribute invoked: (, '__getattribute__') Metaclass getattribute invoked: <bound method C.__getattribute__ of > >>
Las conclusiones que he obtenido son (considerando que estamos buscando x.foo):
¿¿Puede alguien explicar esto, por favor?? o al menos dime dónde puedo encontrar algo de documentación sobre esto, gracias.
Si agregó print("Metaclass getattribute invoked:", self, name)
vería:
>>> c.__getattribute__ Class getattribute invoked: <__main__.C object at 0x2acdbb1430d0> __getattribute__ Metaclass getattribute invoked: __name__ >
La metaclase __getattribute__
se invoca para construir la repr
de la expresión c.__getattribute__
, para que pueda imprimir el __name__
C
btw, __getattribute__
funciona igual para las clases y las metaclases; el atributo se busca primero en la instancia y luego en el tipo de la instancia.
>>> Meta.foo = 1 >>> C.foo ('Metaclass getattribute invoked:', , 'foo') 1 >>> c.foo ('Class getattribute invoked:', <__main__.C object at 0x2acdbb1430d0>, 'foo') Traceback (most recent call last): File "", line 1, in File "", line 5, in __getattribute__ AttributeError: 'C' object has no attribute 'foo' >>> C.bar = 2 >>> c.bar ('Class getattribute invoked:', <__main__.C object at 0x2acdbb1430d0>, 'bar') 2